From 8c18e736e95d2b5976ce42fc56889bbb701a428e Mon Sep 17 00:00:00 2001
From: Sonia Zorba <zorba@oats.inaf.it>
Date: Fri, 21 Apr 2017 16:07:17 +0200
Subject: [PATCH] Big refactoring in order to allow multiple TAP versions (2)

---
 TASMAN-core/pom.xml                           |   2 +-
 .../java/it/inaf/ia2/tsm/ChildEntity.java     |   2 +-
 .../src/main/java/it/inaf/ia2/tsm/Column.java |  21 +-
 .../it/inaf/ia2/tsm/ConsistencyChecks.java    |  18 +-
 .../java/it/inaf/ia2/tsm/EntityProperty.java  |   6 +-
 .../src/main/java/it/inaf/ia2/tsm/Key.java    |  41 +-
 .../main/java/it/inaf/ia2/tsm/KeyColumn.java  |   5 +-
 .../java/it/inaf/ia2/tsm/KeyMetadata.java     | 162 ------
 .../src/main/java/it/inaf/ia2/tsm/Schema.java |   2 -
 .../main/java/it/inaf/ia2/tsm/TSMUtil.java    |  63 ---
 .../src/main/java/it/inaf/ia2/tsm/Table.java  |   1 -
 .../main/java/it/inaf/ia2/tsm/TapSchema.java  | 374 +++++++-------
 .../java/it/inaf/ia2/tsm/TapSchemaEntity.java |  23 +-
 .../it/inaf/ia2/tsm/UpdateOperations.java     |  25 +-
 .../it/inaf/ia2/tsm/datalayer/DBBroker.java   |  11 +-
 .../ia2/tsm/datalayer/DBBrokerTemplate.java   |  48 +-
 .../tsm/datalayer/mysql/MySQLDBBroker.java    |  49 +-
 .../tsm/datalayer/pgsql/PostgresDBBroker.java |   7 +-
 .../{xmlmodel => model}/PropertyModel.java    |   8 +-
 .../{xmlmodel => model}/PropertyXMLModel.java |   2 +-
 .../tsm/{xmlmodel => model}/TableModel.java   |  10 +-
 .../{xmlmodel => model}/TableXMLModel.java    |   2 +-
 .../{xmlmodel => model}/TapSchemaModel.java   |  10 +-
 .../{xmlmodel => model}/TapSchemaModels.java  |  23 +-
 .../TapSchemaXMLModel.java                    |   2 +-
 .../java/it/inaf/ia2/tsm/model/Tasman.java    |  55 +++
 .../src/main/resources/core.properties        |   9 +
 .../resources/tap_schema/tap_schema-1.xml     |   4 -
 .../java/it/inaf/ia2/tsm/api/TestAll.java     | 463 +++++++-----------
 TASMAN-webapp/pom.xml                         |   4 +-
 .../ia2/tsm/webapp/ConsistencyChecksBean.java |   2 +-
 .../ia2/tsm/webapp/SchemaSelectionBean.java   |  29 +-
 .../ia2/tsm/webapp/TapSchemaEditingBean.java  |  22 +-
 .../src/main/webapp/tapSchemaEditing.xhtml    |  24 +-
 34 files changed, 701 insertions(+), 828 deletions(-)
 delete mode 100644 TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyMetadata.java
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/PropertyModel.java (92%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/PropertyXMLModel.java (98%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/TableModel.java (88%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/TableXMLModel.java (98%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/TapSchemaModel.java (87%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/TapSchemaModels.java (84%)
 rename TASMAN-core/src/main/java/it/inaf/ia2/tsm/{xmlmodel => model}/TapSchemaXMLModel.java (98%)
 create mode 100644 TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/Tasman.java
 create mode 100644 TASMAN-core/src/main/resources/core.properties

diff --git a/TASMAN-core/pom.xml b/TASMAN-core/pom.xml
index 9e6f3fa..cec38d2 100644
--- a/TASMAN-core/pom.xml
+++ b/TASMAN-core/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>it.inaf.ia2.tap</groupId>
     <artifactId>tasman-core</artifactId>
-    <version>1.1.0</version>
+    <version>1.2.0</version>
     <packaging>jar</packaging>
     <name>tasman-core</name>
     <properties>
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ChildEntity.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ChildEntity.java
index e6e9e5d..7ff7479 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ChildEntity.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ChildEntity.java
@@ -22,7 +22,7 @@
  */
 package it.inaf.ia2.tsm;
 
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
+import it.inaf.ia2.tsm.model.TableModel;
 import java.util.Map;
 
 /**
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java
index aae711c..6e30960 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java
@@ -43,7 +43,7 @@ public class Column extends ChildEntity<Table> {
     private static final Logger LOG = LoggerFactory.getLogger(Column.class);
 
     private boolean foreignKeySearched;
-    private KeyMetadata foreignKey;
+    private Key foreignKey;
 
     private Table parentTable;
 
@@ -58,9 +58,24 @@ public class Column extends ChildEntity<Table> {
         setStatus(Status.LOADED);
     }
 
-    public KeyMetadata getForeignKey() {
+    public Key getForeignKey() {
         if (!foreignKeySearched) { // lazy loading (but the foreignKey value can be null, so we use this boolean)
-            foreignKey = tapSchema.searchKeyMetadata(parentTable.getParent().getName(), parentTable.getName(), getName());
+
+            String fromSchemaName = parentTable.getParent().getName();
+            String fromTableName = parentTable.getName();
+            String fromColumnName = getName();
+
+            ext:
+            for (Key key : tapSchema.getAllKeys()) {
+                if (key.getFromSchemaName().equals(fromSchemaName) && key.getFromTableSimpleName().equals(fromTableName)) {
+                    for (KeyColumn keyColumn : key.getKeyColumns()) {
+                        if (keyColumn.getFromColumn().equals(fromColumnName)) {
+                            foreignKey = key;
+                            break ext;
+                        }
+                    }
+                }
+            }
         }
 
         return foreignKey;
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ConsistencyChecks.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ConsistencyChecks.java
index 1b9f6d6..d1e9d27 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ConsistencyChecks.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/ConsistencyChecks.java
@@ -74,18 +74,18 @@ public class ConsistencyChecks implements Serializable {
     }
 
     private final List<InconsistentValue> inconsistencies;
-    private final List<String> unexisingSchemas;
-    private final List<String> unexisingTables;
+    private final Set<String> unexisingSchemas;
+    private final Set<String> unexisingTables;
     private final Map<String, String> unexisingColumns;
-    private final List<String> unexistingKeys;
+    private final Set<String> unexistingKeys;
     private final List<UnexistingKeyColumn> unexistingKeyColumns;
 
     public ConsistencyChecks() {
         inconsistencies = new ArrayList<>();
-        unexisingSchemas = new ArrayList<>();
-        unexisingTables = new ArrayList<>();
+        unexisingSchemas = new HashSet<>();
+        unexisingTables = new HashSet<>();
         unexisingColumns = new HashMap<>();
-        unexistingKeys = new ArrayList<>();
+        unexistingKeys = new HashSet<>();
         unexistingKeyColumns = new ArrayList<>();
     }
 
@@ -97,7 +97,7 @@ public class ConsistencyChecks implements Serializable {
         return inconsistencies;
     }
 
-    public List<String> getUnexisingSchemas() {
+    public Set<String> getUnexisingSchemas() {
         return unexisingSchemas;
     }
 
@@ -105,7 +105,7 @@ public class ConsistencyChecks implements Serializable {
         unexisingSchemas.add(schemaName);
     }
 
-    public List<String> getUnexisingTables() {
+    public Set<String> getUnexisingTables() {
         return unexisingTables;
     }
 
@@ -128,7 +128,7 @@ public class ConsistencyChecks implements Serializable {
         unexistingKeys.add(keyId);
     }
 
-    public List<String> getUnexistingKeys() {
+    public Set<String> getUnexistingKeys() {
         return unexistingKeys;
     }
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java
index ec37b22..5074420 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java
@@ -22,7 +22,7 @@
  */
 package it.inaf.ia2.tsm;
 
-import it.inaf.ia2.tsm.xmlmodel.PropertyModel;
+import it.inaf.ia2.tsm.model.PropertyModel;
 import java.io.Serializable;
 
 /**
@@ -111,4 +111,8 @@ public class EntityProperty<T> implements Serializable {
     public void save() {
         this.originalValue = value;
     }
+
+    public Class getType() {
+        return type;
+    }
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java
index dfbe3a1..b16933c 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java
@@ -25,8 +25,11 @@ package it.inaf.ia2.tsm;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.regex.Pattern;
 
 /**
  * The main implementation of {@link Key}.
@@ -41,25 +44,31 @@ public class Key extends TapSchemaEntity implements Serializable {
 
     private static final long serialVersionUID = -8783695875831579336L;
 
-    private KeyMetadata keyMetadata;
     private List<KeyColumn> keyColumns;
-
     private boolean visible;
 
+    private String fromSchema;
+    private String fromTable;
+    private String targetSchema;
+    private String targetTable;
+
     private Key() {
         super();
     }
 
-    public Key(TapSchema tapSchema, KeyMetadata keyMetadata) {
-        super(tapSchema, tapSchema.getTableModel(TapSchema.KEYS_TABLE), keyMetadata.getKeyMetadata());
+    public Key(TapSchema tapSchema, Map<String, Object> metadata) {
+        super(tapSchema, tapSchema.getTableModel(TapSchema.KEYS_TABLE), metadata);
 
-        this.keyMetadata = keyMetadata;
         keyColumns = new ArrayList<>();
         visible = false;
-    }
 
-    public KeyMetadata getKeyMetadata() {
-        return keyMetadata;
+        String[] fromSplit = ((String) metadata.get(FROM_TABLE_KEY)).split(Pattern.quote("."));
+        String[] targetSplit = ((String) metadata.get(TARGET_TABLE_KEY)).split(Pattern.quote("."));
+
+        fromSchema = fromSplit[0];
+        fromTable = fromSplit[1];
+        targetSchema = targetSplit[0];
+        targetTable = targetSplit[1];
     }
 
     public boolean isVisible() {
@@ -86,11 +95,11 @@ public class Key extends TapSchemaEntity implements Serializable {
     }
 
     public String getFromSchemaName() {
-        return keyMetadata.getFromSchema();
+        return fromSchema;
     }
 
     public String getFromTableSimpleName() {
-        return keyMetadata.getFromTable();
+        return fromTable;
     }
 
     public String getFromTableCompleteName() {
@@ -98,11 +107,11 @@ public class Key extends TapSchemaEntity implements Serializable {
     }
 
     public String getTargetSchemaName() {
-        return keyMetadata.getTargetSchema();
+        return targetSchema;
     }
 
     public String getTargetTableSimpleName() {
-        return keyMetadata.getTargetTable();
+        return targetTable;
     }
 
     public String getTargetTableCompleteName() {
@@ -110,13 +119,19 @@ public class Key extends TapSchemaEntity implements Serializable {
     }
 
     public KeyColumn addKeyColumn(String fromColumn, String targetColumn) {
-        KeyColumn keyColumn = new KeyColumn(tapSchema, this, fromColumn, targetColumn);
+        Map<String, Object> keyColumnMetadata = new HashMap<>();
+        keyColumnMetadata.put(KeyColumn.FROM_COLUMN_KEY, fromColumn);
+        keyColumnMetadata.put(KeyColumn.TARGET_COLUMN_KEY, targetColumn);
+        KeyColumn keyColumn = new KeyColumn(tapSchema, this, keyColumnMetadata);
         keyColumns.add(keyColumn);
         return keyColumn;
     }
 
     @Override
     public void save() {
+        if (!isVisible()) {
+            initProperty(ID_KEY, null);
+        }
         super.save();
         for (KeyColumn keyColumn : keyColumns) {
             keyColumn.save();
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyColumn.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyColumn.java
index b7aeb11..af97007 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyColumn.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyColumn.java
@@ -22,6 +22,7 @@
  */
 package it.inaf.ia2.tsm;
 
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -44,8 +45,8 @@ public class KeyColumn extends TapSchemaEntity {
         super();
     }
 
-    protected KeyColumn(TapSchema tapSchema, Key key, String fromColumn, String targetColumn) {
-        super(tapSchema, tapSchema.getTableModel(TapSchema.KEY_COLUMNS_TABLE), key.getKeyMetadata().getKeyColumnMetadata(fromColumn, targetColumn));
+    protected KeyColumn(TapSchema tapSchema, Key key, Map<String, Object> keyColumnMetadata) {
+        super(tapSchema, tapSchema.getTableModel(TapSchema.KEY_COLUMNS_TABLE), keyColumnMetadata);
         this.key = key;
     }
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyMetadata.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyMetadata.java
deleted file mode 100644
index 02b9371..0000000
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyMetadata.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * _____________________________________________________________________________
- * 
- * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of
- * Trieste INAF - IA2 Italian Center for Astronomical Archives
- * _____________________________________________________________________________
- * 
- * Copyright (C) 2017 Istituto Nazionale di Astrofisica
- * 
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License Version 3 as published by the
- * Free Software Foundation.
- * 
- * This program 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
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package it.inaf.ia2.tsm;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- *
- * @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
- */
-public class KeyMetadata implements Serializable {
-
-    public static final String NEW_KEY = "#NEW#";
-    private static final long serialVersionUID = -30688540834789724L;
-
-    private final String fromSchema;
-    private final String fromTable;
-    private final List<String> fromColumns;
-    private final String targetSchema;
-    private final String targetTable;
-    private final List<String> targetColumns;
-
-    public KeyMetadata(String fromSchema, String fromTable, String targetSchema, String targetTable) {
-        this.fromSchema = fromSchema;
-        this.fromTable = fromTable;
-        this.fromColumns = new ArrayList<>();
-        this.targetSchema = targetSchema;
-        this.targetTable = targetTable;
-        this.targetColumns = new ArrayList<>();
-    }
-
-    public String getFromSchema() {
-        return fromSchema;
-    }
-
-    public String getFromTable() {
-        return fromTable;
-    }
-
-    public List<String> getFromColumns() {
-        return fromColumns;
-    }
-
-    public String getTargetSchema() {
-        return targetSchema;
-    }
-
-    public String getTargetTable() {
-        return targetTable;
-    }
-
-    public List<String> getTargetColumns() {
-        return targetColumns;
-    }
-
-    public void addKeyColumn(String fromColumn, String targetColumn) {
-        fromColumns.add(fromColumn);
-        targetColumns.add(targetColumn);
-    }
-
-    public Map<String, Object> getKeyMetadata() {
-        Map<String, Object> metadata = new HashMap<>();
-        metadata.put(Key.ID_KEY, NEW_KEY);
-        metadata.put(Key.FROM_TABLE_KEY, fromSchema + "." + fromTable);
-        metadata.put(Key.TARGET_TABLE_KEY, targetSchema + "." + targetTable);
-        return metadata;
-    }
-
-    public Map<String, Object> getKeyColumnMetadata(String fromColumn, String targetColumn) {
-        Map<String, Object> metadata = new HashMap<>();
-        metadata.put(KeyColumn.KEY_ID_KEY, NEW_KEY);
-        metadata.put(KeyColumn.FROM_COLUMN_KEY, fromColumn);
-        metadata.put(KeyColumn.TARGET_COLUMN_KEY, targetColumn);
-        return metadata;
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 17 * hash + Objects.hashCode(this.fromSchema);
-        hash = 17 * hash + Objects.hashCode(this.fromTable);
-        for (String fromColumn : fromColumns) {
-            hash = 17 * hash + Objects.hashCode(fromColumn);
-        }
-        hash = 17 * hash + Objects.hashCode(this.targetSchema);
-        hash = 17 * hash + Objects.hashCode(this.targetTable);
-        for (String targetColumn : targetColumns) {
-            hash = 17 * hash + Objects.hashCode(targetColumn);
-        }
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final KeyMetadata other = (KeyMetadata) obj;
-        if (!Objects.equals(this.fromSchema, other.fromSchema)) {
-            return false;
-        }
-        if (!Objects.equals(this.fromTable, other.fromTable)) {
-            return false;
-        }
-        if (!Objects.equals(this.targetSchema, other.targetSchema)) {
-            return false;
-        }
-        if (!Objects.equals(this.targetTable, other.targetTable)) {
-            return false;
-        }
-        if (this.fromColumns.size() != other.fromColumns.size()) {
-            return false;
-        }
-        for (int i = 0; i < fromColumns.size(); i++) {
-            String fromColumn = fromColumns.get(i);
-            if (!Objects.equals(fromColumn, other.fromColumns.get(i))) {
-                return false;
-            }
-        }
-        if (this.targetColumns.size() != other.targetColumns.size()) {
-            return false;
-        }
-        for (int i = 0; i < targetColumns.size(); i++) {
-            String targetColumn = targetColumns.get(i);
-            if (!Objects.equals(targetColumn, other.targetColumns.get(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java
index fe02380..ad3df64 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java
@@ -88,8 +88,6 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer<
         LOG.debug("Adding table {} into schema {}", tableSimpleName, schemaName);
 
         if (!tables.containsKey(tableSimpleName)) {
-            //throw new IllegalArgumentException("The table " + tableSimpleName + " doesn't exist into the schema " + schemaName + ". Are you sure you are using the simple table name?");
-            tapSchema.getConsistencyChecks().addUnexistingTable(schemaName, tableSimpleName);
             return null;
         } else {
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java
index a584a6e..418914b 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java
@@ -241,7 +241,6 @@ public class TSMUtil {
 //        column.setDescription(description);
 //        column.setStd(true);
 //    }
-
     public static String getNaturalLangueName(TapSchemaEntity entity) {
         if (entity instanceof Schema) {
             return "schema";
@@ -307,66 +306,4 @@ public class TSMUtil {
 
         return sb.toString();
     }
-
-    /**
-     * Fill descriptions of the TAP_SCHEMA schema entities.
-     *
-     * @param schema the TAP_SCHEMA schema <code>SchemaEntity</code>.
-     */
-    protected static void putInfoIntoTapSchemaSchema(Schema schema) {
-//
-//        schema.setDescription("a special schema to describe a TAP tableset");
-//
-//        // SCHEMAS
-//        Table schemasTable = schema.getChild("schemas");
-//        schemasTable.setDescription("description of schemas in this tableset");
-//
-//        setTSColumnDescription(schemasTable, "schema_name", "schema name for reference to TAP_SCHEMA.schemas");
-//        setTSColumnDescription(schemasTable, "utype", "lists the utypes of schemas in the tableset");
-//        setTSColumnDescription(schemasTable, "description", "describes schemas in the tableset");
-//
-//        // TABLES
-//        Table tablesTable = schema.getChild("tables");
-//        tablesTable.setDescription("description of tables in this tableset");
-//
-//        setTSColumnDescription(tablesTable, "schema_name", "the schema this table belongs to");
-//        setTSColumnDescription(tablesTable, "table_name", "the fully qualified table name");
-//        setTSColumnDescription(tablesTable, "table_type", "one of: table view");
-//        setTSColumnDescription(tablesTable, "utype", "lists the utype of tables in the tableset");
-//        setTSColumnDescription(tablesTable, "description", "describes tables in the tableset");
-//
-//        // COLUMNS
-//        Table columnsTable = schema.getChild("columns");
-//        columnsTable.setDescription("description of columns in this tableset");
-//
-//        setTSColumnDescription(columnsTable, "table_name", "the table this column belongs to");
-//        setTSColumnDescription(columnsTable, "column_name", "the column name");
-//        setTSColumnDescription(columnsTable, "utype", "lists the utypes of columns in the tableset");
-//        setTSColumnDescription(columnsTable, "ucd", "lists the UCDs of columns in the tableset");
-//        setTSColumnDescription(columnsTable, "unit", "lists the unit used for column values in the tableset");
-//        setTSColumnDescription(columnsTable, "description", "describes the columns in the tableset");
-//        setTSColumnDescription(columnsTable, "datatype", "lists the ADQL datatype of columns in the tableset");
-//        setTSColumnDescription(columnsTable, "size", "lists the size of variable-length columns in the tableset");
-//        setTSColumnDescription(columnsTable, "principal", "a principal column; 1 means 1, 0 means 0");
-//        setTSColumnDescription(columnsTable, "indexed", "an indexed column; 1 means 1, 0 means 0");
-//        setTSColumnDescription(columnsTable, "std", "a standard column; 1 means 1, 0 means 0");
-//
-//        // KEYS
-//        Table keysTable = schema.getChild("keys");
-//        keysTable.setDescription("description of foreign keys in this tableset");
-//
-//        setTSColumnDescription(keysTable, "key_id", "unique key to join to TAP_SCHEMA.key_columns");
-//        setTSColumnDescription(keysTable, "from_table", "the table with the foreign key");
-//        setTSColumnDescription(keysTable, "target_table", "the table with the primary key");
-//        setTSColumnDescription(keysTable, "utype", "lists the utype of keys in the tableset");
-//        setTSColumnDescription(keysTable, "description", "describes keys in the tableset");
-//
-//        // KEY COLUMNS
-//        Table keyColumnsTable = schema.getChild("key_columns");
-//        keyColumnsTable.setDescription("description of foreign key columns in this tableset");
-//
-//        setTSColumnDescription(keyColumnsTable, "key_id", "key to join to TAP_SCHEMA.keys");
-//        setTSColumnDescription(keyColumnsTable, "from_column", "column in the from_table");
-//        setTSColumnDescription(keyColumnsTable, "target_column", "column in the target_table");
-    }
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java
index 4ad2590..6446101 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java
@@ -101,7 +101,6 @@ public class Table extends ChildEntity<Schema> implements EntitiesContainer<Colu
         LOG.debug("Adding column {} into table {}", columnName, tableCompleteName);
 
         if (!columns.containsKey(columnName)) {
-            tapSchema.getConsistencyChecks().addUnexistingColumn(getCompleteName(), columnName);
             return null;
         } else {
             Column column = columns.get(columnName);
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java
index 4b008b7..e1c285c 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java
@@ -25,9 +25,10 @@ package it.inaf.ia2.tsm;
 import it.inaf.ia2.tsm.datalayer.DBBroker;
 import it.inaf.ia2.tsm.datalayer.DBBrokerFactory;
 import it.inaf.ia2.tsm.datalayer.DBWrapper;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
-import it.inaf.ia2.tsm.xmlmodel.TapSchemaModel;
-import it.inaf.ia2.tsm.xmlmodel.TapSchemaModels;
+import it.inaf.ia2.tsm.model.PropertyModel;
+import it.inaf.ia2.tsm.model.TableModel;
+import it.inaf.ia2.tsm.model.TapSchemaModel;
+import it.inaf.ia2.tsm.model.TapSchemaModels;
 import java.io.Serializable;
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -37,6 +38,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.regex.Pattern;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,13 +55,13 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
     public static final String COLUMNS_TABLE = "columns";
     public static final String KEYS_TABLE = "keys";
     public static final String KEY_COLUMNS_TABLE = "key_columns";
+    public static final String DESCRIPTION_KEY = "description";
 
     private static final long serialVersionUID = 1678083091602571256L;
 
     private static final Logger LOG = LoggerFactory.getLogger(TapSchema.class);
 
     private final Map<String, Schema> schemas;
-    private final List<KeyMetadata> keysMetadata;
     private final Set<Key> allKeys;
     private final ConsistencyChecks consistencyChecks;
 
@@ -90,7 +92,6 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
         // for serialization
         schemas = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         allKeys = new HashSet<>();
-        keysMetadata = new ArrayList<>();
         consistencyChecks = new ConsistencyChecks();
     }
 
@@ -109,16 +110,130 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
         }
         schemas.put(tapSchemaName, null); // the TAP_SCHEMA contains itself
 
-//        if (exists) {
-//            DaoSchema.fillSavedSchemas(dbWrapper, (this));
-//            DaoTable.fillSavedTables(dbWrapper, (this));
-//            DaoColumn.fillSavedColumns(dbWrapper, (this));
-//            DaoKey.fillSavedKeys(dbWrapper, (this));
-//        }
+        if (exists) {
+            loadSavedTapSchema();
+        }
+
         loading = false;
         checkKeys();
     }
 
+    /**
+     * Loads saved TAP_SCHEMA data and performs consistency checking.
+     *
+     * @throws SQLException
+     */
+    private void loadSavedTapSchema() throws SQLException {
+        DBBroker broker = getTapSchemaDBBroker();
+
+        // Schemata
+        for (Map<String, Object> schemaProps : broker.getSavedItems(getName(), getTableModel(SCHEMAS_TABLE))) {
+            String schemaName = (String) schemaProps.get(Schema.SCHEMA_NAME_KEY);
+            Schema schema = addChild(schemaName);
+            if (schema == null) {
+                consistencyChecks.addUnexistingSchema(schemaName);
+            } else {
+                schema.init(schemaProps);
+                schema.setStatus(Status.ADDED_PERSISTED);
+            }
+        }
+
+        // Tables
+        for (Map<String, Object> tableProps : broker.getSavedItems(getName(), getTableModel(TABLES_TABLE))) {
+            String tableCompleteName = (String) tableProps.get(Table.TABLE_NAME_KEY);
+            String[] tableNameSplit = tableCompleteName.split(Pattern.quote("."));
+            String schemaName = tableNameSplit[0];
+            String tableName = tableNameSplit[1];
+            Schema schema = getChild(schemaName, Status.ADDED_PERSISTED);
+            if (schema == null) {
+                consistencyChecks.addUnexistingSchema(schemaName);
+            } else {
+                Table table = schema.addChild(tableName);
+                if (table == null) {
+                    consistencyChecks.addUnexistingTable(schemaName, tableName);
+                } else {
+                    table.init(tableProps);
+                    table.setStatus(Status.ADDED_PERSISTED);
+                }
+            }
+        }
+
+        // Columns
+        for (Map<String, Object> columnProps : broker.getSavedItems(getName(), getTableModel(COLUMNS_TABLE))) {
+            String tableCompleteName = (String) columnProps.get(Column.TABLE_NAME_KEY);
+            String[] tableNameSplit = tableCompleteName.split(Pattern.quote("."));
+            String schemaName = tableNameSplit[0];
+            String tableName = tableNameSplit[1];
+            String columnName = (String) columnProps.get(Column.COLUMN_NAME_KEY);
+            Schema schema = getChild(schemaName, Status.ADDED_PERSISTED);
+            if (schema == null) {
+                consistencyChecks.addUnexistingSchema(schemaName);
+            } else {
+                Table table = schema.getChild(tableName, Status.ADDED_PERSISTED);
+                if (table == null) {
+                    consistencyChecks.addUnexistingTable(schemaName, tableName);
+                } else {
+                    Column column = table.addChild(columnName);
+                    if (column == null) {
+                        consistencyChecks.addUnexistingColumn(tableCompleteName, columnName);
+                    } else {
+                        column.init(columnProps);
+                        column.setStatus(Status.ADDED_PERSISTED);
+                    }
+                }
+            }
+        }
+
+        // Keys
+        List<Map<String, Object>> keysProps = broker.getSavedItems(getName(), getTableModel(KEYS_TABLE));
+        List<Map<String, Object>> keysColumnsProps = broker.getSavedItems(getName(), getTableModel(KEY_COLUMNS_TABLE));
+        for (Map<String, Object> keyProp : keysProps) {
+            // Searching the key
+            boolean keyFound = false;
+            for (Key key : allKeys) {
+                String fromTable = (String) keyProp.get(Key.FROM_TABLE_KEY);
+                String targetTable = (String) keyProp.get(Key.TARGET_TABLE_KEY);
+                if (key.getFromTableCompleteName().equals(fromTable) && key.getTargetTableCompleteName().equals(targetTable)) {
+                    // Search the key columns having proper key id
+                    List<Map<String, Object>> kcPropsById = new ArrayList<>();
+                    for (Map<String, Object> kcp : keysColumnsProps) {
+                        if (kcp.get(KeyColumn.KEY_ID_KEY).equals(key.getId())) {
+                            kcPropsById.add(kcp);
+                        }
+                    }
+
+                    // Verifying the matching
+                    List<KeyColumn> matchedKeyColumns = new ArrayList<>();
+                    if (kcPropsById.size() == key.getKeyColumns().size()) {
+                        for (Map<String, Object> kcp : kcPropsById) {
+                            String fromColumn = (String) kcp.get(KeyColumn.FROM_COLUMN_KEY);
+                            String targetColumn = (String) kcp.get(KeyColumn.TARGET_COLUMN_KEY);
+                            for (KeyColumn keyColumn : key.getKeyColumns()) {
+                                if (keyColumn.getFromColumn().equals(fromColumn)
+                                        && keyColumn.getTargetColumn().equals(targetColumn)) {
+                                    matchedKeyColumns.add(keyColumn);
+                                }
+                            }
+                        }
+                    }
+                    if (kcPropsById.size() == matchedKeyColumns.size()) {
+                        keyFound = true;
+                        int index = 0;
+                        key.init(keyProp);
+                        for (Map<String, Object> kcp : kcPropsById) {
+                            KeyColumn kc = matchedKeyColumns.get(index);
+                            kc.init(kcp);
+                            index++;
+                        }
+                    }
+                }
+            }
+            if (!keyFound) {
+                // TODO
+            }
+        }
+    }
+
     public DBBroker getDBBroker(String schemaName) {
         if (schemaName.equals(tapSchemaName)) {
             return getTapSchemaDBBroker();
@@ -130,7 +245,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
     /**
      * The name of the TAP_SCHEMA schema.
      */
-    public String getName() {
+    public final String getName() {
         return tapSchemaName;
     }
 
@@ -142,10 +257,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
     }
 
     private void loadSchemaKeysMetadata(String schemaName) throws SQLException {
-        keysMetadata.addAll(getDBBroker(schemaName).getKeysMetadata(schemaName));
+        allKeys.addAll(getDBBroker(schemaName).getKeys(this, schemaName));
     }
 
-    protected Set<Key> getAllKeys() {
+    public Set<Key> getAllKeys() {
         return allKeys;
     }
 
@@ -153,14 +268,12 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
      * {@inheritDoc}
      */
     @Override
-    public Schema addChild(String schemaName) throws SQLException {
+    public final Schema addChild(String schemaName) throws SQLException {
         LOG.debug("Adding schema {}", schemaName);
 
         Schema schema;
 
         if (!schemas.containsKey(schemaName)) {
-
-            consistencyChecks.addUnexistingSchema(schemaName);
             schema = null;
         } else {
 
@@ -183,9 +296,9 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
                         throw new IllegalArgumentException("Cannot add the schema " + schemaName + ". Invalid status. Schema status is " + schema.getStatus());
                 }
             }
-        }
 
-        checkKeys();
+            checkKeys();
+        }
 
         return schema;
     }
@@ -219,7 +332,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
      * {@inheritDoc}
      */
     @Override
-    public Schema getChild(String childName, Status... statuses) {
+    public final Schema getChild(String childName, Status... statuses) {
         return TSMUtil.getChild(schemas, childName, statuses);
     }
 
@@ -272,13 +385,11 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
      */
     public void save() throws SQLException {
 
-        fillKeyIds();
-
         DBBroker broker = getTapSchemaDBBroker();
 
-        broker.save(this);
-
         if (!exists) {
+            broker.createTapSchemaStructure(getName(), getTapSchemaModel());
+
             // Adding TAP_SCHEMA into TAP_SCHEMA
             Schema tapSchemaSchema = addChild(tapSchemaName);
             for (String tableName : tapSchemaSchema.getAddableChildrenNames()) {
@@ -287,14 +398,13 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
                     table.addChild(columnName);
                 }
             }
-            LOG.debug(this.toString());
-            TSMUtil.putInfoIntoTapSchemaSchema(tapSchemaSchema);
-
-            exists = true; // important!
 
-            //broker.save(this); // save again
+            fillTapSchemaDescriptions();
         }
 
+        fillKeyIds();
+
+        broker.save(this);
         exists = true;
 
         consistencyChecks.getInconsistencies().clear();
@@ -309,7 +419,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
     private int getMaxKeyId() {
         int maxKeyId = 0;
         for (Key key : allKeys) {
-            if (key.getId() != null && !KeyMetadata.NEW_KEY.equals(key.getId())) {
+            if (key.getId() != null) {
                 int keyId = Integer.parseInt(key.getId());
                 if (keyId > maxKeyId) {
                     maxKeyId = keyId;
@@ -323,7 +433,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
 
         List<Key> newKeys = new ArrayList<>();
         for (Key key : allKeys) {
-            if (key.isVisible() && KeyMetadata.NEW_KEY.equals(key.getId())) {
+            if (key.isVisible()) {
                 newKeys.add(key);
             }
         }
@@ -335,56 +445,6 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
         }
     }
 
-//    /**
-//     * Set keys visibility based on other entities visibility (a key is visible
-//     * if all schemas, tables and columns involved have
-//     * {@link Status} {@code ADDED_PERSISTED} or {@code ADDED_NOT_PERSISTED}).
-//     */
-//    protected void checkKeys() {
-//
-//        int currentKey = getMaxKeyId() + 1;
-//
-//        for (Key key : allKeys) {
-//
-//            ((Key) key).setVisible(false);
-//
-//            Schema fromSchema = getChild(key.getFromSchemaName(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//            Schema targetSchema = getChild(key.getTargetSchemaName(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//            if (fromSchema != null && targetSchema != null) {
-//
-//                Table fromTable = fromSchema.getChild(key.getFromTableSimpleName(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//                Table targetTable = targetSchema.getChild(key.getTargetTableSimpleName(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//
-//                if (fromTable != null && targetTable != null) {
-//
-//                    boolean allColumnsVisible = true;
-//
-//                    for (KeyColumn keyColumn : key.getKeyColumns()) {
-//
-//                        Column fromColumn = fromTable.getChild(keyColumn.getFromColumn(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//                        Column targetColumn = targetTable.getChild(keyColumn.getTargetColumn(), Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
-//
-//                        if (fromColumn == null || targetColumn == null) {
-//                            allColumnsVisible = false;
-//                            break;
-//                        }
-//                    }
-//
-//                    if (allColumnsVisible) {
-//                        ((Key) key).setVisible(true);
-//                        if (key.getId() == null) {
-//                            key.setId(currentKey + "");
-//                            currentKey++;
-//                        }
-//                    }
-//                }
-//            }
-//        }
-//        for (Key key : allKeys) {
-//            log.debug("{} [{}]", key, key.getStatus());
-//        }
-//    }
-//
 //    public void addFictitiousKey(Table fromTable, String[] fromColumns, Table targetTable, String[] targetColumns) {
 //        Key key = new Key(dbWrapper, this, fromTable.getCompleteName(), targetTable.getCompleteName());
 //        key.setId((getMaxKeyId() + 1) + "");
@@ -400,49 +460,38 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
 //        checkKeys();
 //    }
     /**
-     * Automatically add and remove keys that should be visible.
+     * Set keys visibility based on other entities visibility (a key is visible
+     * if all schemas, tables and columns involved have
+     * {@link Status} {@code ADDED_PERSISTED} or {@code ADDED_NOT_PERSISTED}).
      */
     public final void checkKeys() {
         if (!loading) {
 
-            for (KeyMetadata keyMetadata : keysMetadata) {
+            for (Key key : allKeys) {
 
                 // Check if key should be exposed in TAP_SCHEMA
                 boolean keyVisible = true;
 
-                for (String fromColumn : keyMetadata.getFromColumns()) {
-                    if (!isColumnVisible(keyMetadata.getFromSchema(), keyMetadata.getFromTable(), fromColumn)) {
+                for (KeyColumn keyColumn : key.getKeyColumns()) {
+                    String schemaName = keyColumn.getParent().getFromSchemaName();
+                    String tableName = keyColumn.getParent().getFromTableSimpleName();
+                    String columnName = keyColumn.getFromColumn();
+                    if (!isColumnVisible(schemaName, tableName, columnName)) {
                         keyVisible = false;
                         break;
                     }
-                }
-                if (keyVisible) {
-                    for (String targetColumn : keyMetadata.getTargetColumns()) {
-                        if (!isColumnVisible(keyMetadata.getTargetSchema(), keyMetadata.getTargetTable(), targetColumn)) {
-                            keyVisible = false;
-                            break;
-                        }
-                    }
-                }
 
-                Key key = null;
-                for (Key k : allKeys) {
-                    if (k.getKeyMetadata().equals(keyMetadata)) {
-                        key = k;
+                    schemaName = keyColumn.getParent().getTargetSchemaName();
+                    tableName = keyColumn.getParent().getTargetTableSimpleName();
+                    columnName = keyColumn.getTargetColumn();
+                    if (!isColumnVisible(schemaName, tableName, columnName)) {
+                        keyVisible = false;
                         break;
                     }
                 }
 
                 // TODO: use status instead of set visibile [?]
-                if (keyVisible) {
-                    if (key == null) {
-                        key = new Key(this, keyMetadata);
-                        allKeys.add(key);
-                    }
-                    key.setVisible(true);
-                } else if (key != null) {
-                    key.setVisible(false);
-                }
+                key.setVisible(keyVisible);
             }
         }
     }
@@ -457,55 +506,39 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
 
         sb.append(String.format(">> TAP_SCHEMA %s <<\n", tapSchemaName));
 
-//        for (Schema schema : getChildren()) {
-//            sb.append("--");
-//            sb.append(schema.getName());
-//            sb.append(String.format(" [%s]", schema.getStatus()));
-//            sb.append("\n");
-//            List<Table> tables = schema.getChildren();
-//            for (int i = 0; i < tables.size(); i++) {
-//                Table table = tables.get(i);
-//                sb.append("   |--");
-//                sb.append(table.getName());
-//                sb.append(String.format(" [%s]", table.getStatus()));
-//                sb.append("\n");
-//
-//                String padder = i < tables.size() - 1 ? "   |   " : "       ";
-//
-//                for (Column column : table.getChildren()) {
-//                    sb.append(padder);
-//                    sb.append("|--");
-//                    sb.append(column.getName());
-//                    sb.append(String.format(" [%s]", column.getStatus()));
-//                    sb.append("\n");
-//                }
-//
-//                if (table.getAllFromKeys().size() > 0) {
-//                    sb.append(padder);
-//                    sb.append("** From keys **\n");
-//                    for (Key fromKey : table.getAllFromKeys()) {
-//                        sb.append(padder);
-//                        sb.append("* ");
-//                        sb.append(fromKey.toString());
-//                        sb.append(String.format(" [visible=%s]", fromKey.isVisible()));
-//                        sb.append("\n");
-//                    }
-//                }
-//                if (table.getAllTargetKeys().size() > 0) {
-//                    sb.append(padder);
-//                    sb.append("** Target keys **\n");
-//                    for (Key targetKey : table.getAllTargetKeys()) {
-//                        sb.append(padder);
-//                        sb.append("* ");
-//                        sb.append(targetKey.toString());
-//                        sb.append(String.format(" [visible=%s]", targetKey.isVisible()));
-//                        sb.append("\n");
-//                    }
-//                }
-//
-//                sb.append("\n");
-//            }
-//        }
+        for (Schema schema : getChildren()) {
+            sb.append("--");
+            sb.append(schema.getName());
+            sb.append(String.format(" [%s]", schema.getStatus()));
+            sb.append("\n");
+            List<Table> tables = schema.getChildren();
+            for (int i = 0; i < tables.size(); i++) {
+                Table table = tables.get(i);
+                sb.append("   |--");
+                sb.append(table.getName());
+                sb.append(String.format(" [%s]", table.getStatus()));
+                sb.append("\n");
+
+                String padder = i < tables.size() - 1 ? "   |   " : "       ";
+
+                for (Column column : table.getChildren()) {
+                    sb.append(padder);
+                    sb.append("|--");
+                    sb.append(column.getName());
+                    sb.append(String.format(" [%s]", column.getStatus()));
+                    sb.append("\n");
+                }
+
+                sb.append("\n");
+            }
+        }
+
+        sb.append("** Keys **\n");
+        for (Key key : getVisibileKeys()) {
+            sb.append(key);
+            sb.append("\n");
+        }
+
         return sb.toString();
     }
 
@@ -569,20 +602,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
         return TapSchemaModels.getTapSchemaModel(version);
     }
 
-    public TableModel getTableModel(String tableName) {
+    public final TableModel getTableModel(String tableName) {
         return getTapSchemaModel().getTables().get(tableName);
     }
 
-    public KeyMetadata searchKeyMetadata(String fromSchemaName, String fromTableName, String fromColumnName) {
-        for (KeyMetadata km : keysMetadata) {
-            if (km.getFromSchema().equals(fromSchemaName) && km.getFromTable().equals(fromTableName)
-                    && km.getFromColumns().contains(fromColumnName)) {
-                return km;
-            }
-        }
-        return null;
-    }
-
     public Map<String, Object> getSchemaMetadata(String schemaName) {
         Map<String, Object> metadata = new HashMap<>();
         metadata.put(Schema.SCHEMA_NAME_KEY, schemaName);
@@ -598,4 +621,21 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
         }
         return visibleKeys;
     }
+
+    /**
+     * Fill descriptions of the TAP_SCHEMA schema entities.
+     */
+    private void fillTapSchemaDescriptions() {
+        TapSchemaModel tapSchemaModel = getTapSchemaModel();
+        Schema tapSchema = getChild(tapSchemaName);
+        tapSchema.setValue(DESCRIPTION_KEY, tapSchemaModel.getDescription());
+        for (TableModel tableModel : getTapSchemaModel().getTables().values()) {
+            Table table = tapSchema.getChild(tableModel.getName());
+            table.setValue(DESCRIPTION_KEY, tableModel.getDescription());
+            for (PropertyModel propertyModel : tableModel.getProperties().values()) {
+                Column column = table.getChild(propertyModel.getName());
+                column.setValue(DESCRIPTION_KEY, propertyModel.getDescription());
+            }
+        }
+    }
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java
index 86aa23d..a7705df 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java
@@ -22,8 +22,8 @@
  */
 package it.inaf.ia2.tsm;
 
-import it.inaf.ia2.tsm.xmlmodel.PropertyModel;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
+import it.inaf.ia2.tsm.model.PropertyModel;
+import it.inaf.ia2.tsm.model.TableModel;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -85,6 +85,15 @@ public abstract class TapSchemaEntity implements Serializable {
         properties.get(key).init(value);
     }
 
+    /**
+     * Fill saved properties.
+     */
+    public void init(Map<String, Object> props) {
+        for (Map.Entry<String, Object> entry : props.entrySet()) {
+            initProperty(entry.getKey(), entry.getValue());
+        }
+    }
+
     protected String getVersion() {
         return tapSchema.getVersion();
     }
@@ -103,6 +112,14 @@ public abstract class TapSchemaEntity implements Serializable {
     }
 
     public Object getValue(String key) {
+        return properties.get(key).getValue();
+    }
+
+    public Class getPropertyType(String key) {
+        return properties.get(key).getType();
+    }
+
+    public EntityProperty getProperty(String key) {
         return properties.get(key);
     }
 
@@ -125,7 +142,7 @@ public abstract class TapSchemaEntity implements Serializable {
      * @return
      */
     public <T> T getOriginalValue(String key, Class<T> type) {
-        return (T) properties.get(key).getValue();
+        return (T) properties.get(key).getOriginalValue(type);
     }
 
     /**
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java
index ff8357c..235a079 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java
@@ -22,10 +22,6 @@
  */
 package it.inaf.ia2.tsm;
 
-import it.inaf.ia2.tsm.datalayer.DBBroker;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 import org.slf4j.Logger;
@@ -94,20 +90,17 @@ public class UpdateOperations {
         keysToAdd = new ArrayList<>();
         keysToUpdate = new ArrayList<>();
 
-        for (Key key : ((TapSchema) tapSchema).getAllKeys()) {
+        for (Key key : tapSchema.getAllKeys()) {
 
-            if (key.getId() != null) {
-
-                if (key.isVisible()) {
-                    String originalKeyId = key.getOriginalValue(Key.ID_KEY, String.class);
-                    if (originalKeyId == null || KeyMetadata.NEW_KEY.equals(originalKeyId)) {
-                        keysToAdd.add(key);
-                    } else if (key.isChanged()) {
-                        keysToUpdate.add(key);
-                    }
-                } else {
-                    keysToRemove.add(key);
+            if (key.isVisible()) {
+                String originalKeyId = key.getOriginalValue(Key.ID_KEY, String.class);
+                if (originalKeyId == null) {
+                    keysToAdd.add(key);
+                } else if (key.isChanged()) {
+                    keysToUpdate.add(key);
                 }
+            } else if (key.getId() != null) {
+                keysToRemove.add(key);
             }
         }
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java
index 48acab3..d187043 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java
@@ -22,10 +22,11 @@
  */
 package it.inaf.ia2.tsm.datalayer;
 
-import it.inaf.ia2.tsm.KeyMetadata;
+import it.inaf.ia2.tsm.Key;
 import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.TapSchemaEntity;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
+import it.inaf.ia2.tsm.model.TableModel;
+import it.inaf.ia2.tsm.model.TapSchemaModel;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
@@ -42,6 +43,8 @@ public interface DBBroker {
     List<String> getAllSchemaNames() throws SQLException;
 
     List<String> getAllTAPSchemaNames(List<String> allSchemas) throws SQLException;
+    
+    List<String> getExposedSchemas(String tapSchemaName) throws SQLException;
 
     List<String> getAllTablesNames(String schemaName) throws SQLException;
 
@@ -51,7 +54,7 @@ public interface DBBroker {
 
     Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName) throws SQLException;
 
-    List<KeyMetadata> getKeysMetadata(String schemaName) throws SQLException;
+    List<Key> getKeys(TapSchema tapSchema, String schemaName) throws SQLException;
 
     List<Map<String, Object>> getSavedItems(String tapSchemaName, TableModel tableModel, String whereCondition, Object[] whereParams) throws SQLException;
 
@@ -61,5 +64,7 @@ public interface DBBroker {
 
     void updateItem(String tapSchemaName, TapSchemaEntity entity, Connection conn, String whereCondition, Object... whereParams) throws SQLException;
 
+    void createTapSchemaStructure(String tapSchemaName, TapSchemaModel tapSchemaModel) throws SQLException;
+
     void save(TapSchema tapSchema) throws SQLException;
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java
index c283b39..5e42f12 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java
@@ -32,9 +32,9 @@ import it.inaf.ia2.tsm.Table;
 import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.TapSchemaEntity;
 import it.inaf.ia2.tsm.UpdateOperations;
-import it.inaf.ia2.tsm.xmlmodel.PropertyModel;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
-import it.inaf.ia2.tsm.xmlmodel.TapSchemaModel;
+import it.inaf.ia2.tsm.model.PropertyModel;
+import it.inaf.ia2.tsm.model.TableModel;
+import it.inaf.ia2.tsm.model.TapSchemaModel;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -120,7 +120,8 @@ public abstract class DBBrokerTemplate implements DBBroker {
 
     protected abstract void createDatabase(String databaseName, Connection conn) throws SQLException;
 
-    private void createTapSchemaStructure(String tapSchemaName, TapSchemaModel tapSchemaModel) throws SQLException {
+    @Override
+    public void createTapSchemaStructure(String tapSchemaName, TapSchemaModel tapSchemaModel) throws SQLException {
 
         try (Connection conn = dataSource.getConnection()) {
 
@@ -165,10 +166,6 @@ public abstract class DBBrokerTemplate implements DBBroker {
 
         try {
 
-            if (!tapSchema.exists()) {
-                createTapSchemaStructure(tapSchema.getName(), tapSchema.getTapSchemaModel());
-            }
-
             connection = dataSource.getConnection();
 
             UpdateOperations operations = new UpdateOperations(tapSchema);
@@ -255,7 +252,9 @@ public abstract class DBBrokerTemplate implements DBBroker {
             for (Key key : operations.getKeysToAdd()) {
                 // insert new keys and their key columns
                 insertItem(tapSchema.getName(), key, connection);
-                // TODO: INSERT COLUMNS!!!
+                for (KeyColumn keyColumn : key.getKeyColumns()) {
+                    insertItem(tapSchema.getName(), keyColumn, connection);
+                }
             }
 
             //UPDATE ELEMENTS
@@ -264,6 +263,10 @@ public abstract class DBBrokerTemplate implements DBBroker {
                     // update keys and their key columns
                     String whereCond = String.format("%s = ?", escape(Key.ID_KEY));
                     updateItem(tapSchema.getName(), key, connection, whereCond, key.getId());
+                    for (KeyColumn keyColumn : key.getKeyColumns()) {
+                        whereCond = String.format("%s = ?", escape(KeyColumn.KEY_ID_KEY));
+                        updateItem(tapSchema.getName(), keyColumn, connection, whereCond, keyColumn.getKeyId());
+                    }
                 }
 
                 for (Schema schema : operations.getSchemasToUpdate()) {
@@ -485,7 +488,7 @@ public abstract class DBBrokerTemplate implements DBBroker {
                 }
             }
 
-            LOG.debug("Executing query {} [{}]", query, values);
+            LOG.debug("Executing query {} {}", query, values);
             statement.executeUpdate();
         }
     }
@@ -517,7 +520,7 @@ public abstract class DBBrokerTemplate implements DBBroker {
 
         try (PreparedStatement ps = conn.prepareStatement(query)) {
 
-            int i = 0;
+            int i = 1;
 
             List<Object> statParams = null;
             if (LOG.isDebugEnabled()) {
@@ -525,7 +528,7 @@ public abstract class DBBrokerTemplate implements DBBroker {
             }
             for (String key : tapSchemaItem.getPropertiesKeys()) {
                 Object value = tapSchemaItem.getValue(key);
-                ps.setObject(i, value, getSQLType(value.getClass()));
+                ps.setObject(i, value, getSQLType(tapSchemaItem.getPropertyType(key)));
                 i++;
                 if (statParams != null) {
                     statParams.add(value);
@@ -539,7 +542,7 @@ public abstract class DBBrokerTemplate implements DBBroker {
                 }
             }
 
-            LOG.debug("Executing query: {} [{}]", query, statParams);
+            LOG.debug("Executing query: {} {}", query, statParams);
 
             ps.executeUpdate();
         }
@@ -628,4 +631,23 @@ public abstract class DBBrokerTemplate implements DBBroker {
 
         return tablesTypes;
     }
+
+    public List<String> getExposedSchemas(String tapSchemaName) throws SQLException {
+
+        final List<String> exposedSchemas = new ArrayList<>();
+
+        String query = String.format("SELECT %s FROM %s.%s", Schema.SCHEMA_NAME_KEY, escape(tapSchemaName), escape(TapSchema.SCHEMAS_TABLE));
+
+        LOG.debug("Executing query " + query);
+
+        try (Connection connection = dataSource.getConnection();
+                Statement statement = connection.createStatement();
+                ResultSet resultSet = statement.executeQuery(query)) {
+            while (resultSet.next()) {
+                exposedSchemas.add(resultSet.getString(1));
+            }
+        }
+
+        return exposedSchemas;
+    }
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java
index 99a26ad..9998aba 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java
@@ -23,11 +23,12 @@
 package it.inaf.ia2.tsm.datalayer.mysql;
 
 import it.inaf.ia2.tsm.Column;
-import it.inaf.ia2.tsm.KeyMetadata;
+import it.inaf.ia2.tsm.Key;
+import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.datalayer.ADQL;
 import it.inaf.ia2.tsm.datalayer.DBBrokerTemplate;
-import it.inaf.ia2.tsm.xmlmodel.PropertyModel;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
+import it.inaf.ia2.tsm.model.PropertyModel;
+import it.inaf.ia2.tsm.model.TableModel;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -102,12 +103,12 @@ public class MySQLDBBroker extends DBBrokerTemplate {
 
                 // Key info
                 String keyType = resultSet.getString("Key");
-                if ("PRI".equals(keyType)) {
-                    cm.put(Column.PRIMARY_KEY, true);
-                }
-                if ("PRI".equals(keyType) || "UNI".equals(keyType) || "MUL".equals(keyType)) {
-                    cm.put(Column.INDEXED_KEY, true);
-                }
+
+                boolean primaryKey = "PRI".equals(keyType);
+                cm.put(Column.PRIMARY_KEY, primaryKey);
+
+                boolean indexed = "PRI".equals(keyType) || "UNI".equals(keyType) || "MUL".equals(keyType);
+                cm.put(Column.INDEXED_KEY, indexed);
 
                 // Datatype and Size
                 String type = resultSet.getString("Type").toLowerCase();
@@ -221,7 +222,7 @@ public class MySQLDBBroker extends DBBrokerTemplate {
     }
 
     @Override
-    public List<KeyMetadata> getKeysMetadata(String schemaName) throws SQLException {
+    public List<Key> getKeys(TapSchema tapSchema, String schemaName) throws SQLException {
         StringBuilder sb = new StringBuilder();
 
         sb.append("SELECT\n");
@@ -246,7 +247,7 @@ public class MySQLDBBroker extends DBBrokerTemplate {
 
         LOG.debug("Executing query: {}", query);
 
-        List<KeyMetadata> keysMetadata = new ArrayList<>();
+        List<Key> keys = new ArrayList<>();
         try (Connection connection = dataSource.getConnection();
                 Statement statement = connection.createStatement();
                 ResultSet resultSet = statement.executeQuery(query)) {
@@ -259,14 +260,30 @@ public class MySQLDBBroker extends DBBrokerTemplate {
                 String targetSchemaName = resultSet.getString("target_schema");
                 String targetTableName = resultSet.getString("target_table");
 
-                KeyMetadata km = new KeyMetadata(fromSchemaName, fromTableName, targetSchemaName, targetTableName);
-                km.addKeyColumn(resultSet.getString("from_column"), resultSet.getString("target_column"));
-
-                keysMetadata.add(km);
+                Map<String, Object> keyMetadata = new HashMap<>();
+                keyMetadata.put(Key.FROM_TABLE_KEY, fromSchemaName + "." + fromTableName);
+                keyMetadata.put(Key.TARGET_TABLE_KEY, targetSchemaName + "." + targetTableName);
+
+                Key key = null;
+                // Searching for a partial built key
+                for (Key k : keys) {
+                    if (k.getFromSchemaName().equals(fromSchemaName)
+                            && k.getFromTableSimpleName().equals(fromTableName)
+                            && k.getTargetSchemaName().equals(targetSchemaName)
+                            && k.getTargetTableSimpleName().equals(targetTableName)) {
+                        key = k;
+                        break;
+                    }
+                }
+                if (key == null) {
+                    key = new Key(tapSchema, keyMetadata);
+                    keys.add(key);
+                }
+                key.addKeyColumn(resultSet.getString("from_column"), resultSet.getString("target_column"));
             }
         }
 
-        return keysMetadata;
+        return keys;
     }
 
     @Override
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java
index 94a41df..b27016a 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java
@@ -22,9 +22,10 @@
  */
 package it.inaf.ia2.tsm.datalayer.pgsql;
 
-import it.inaf.ia2.tsm.KeyMetadata;
+import it.inaf.ia2.tsm.Key;
+import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.datalayer.DBBrokerTemplate;
-import it.inaf.ia2.tsm.xmlmodel.TableModel;
+import it.inaf.ia2.tsm.model.TableModel;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
@@ -97,7 +98,7 @@ public class PostgresDBBroker extends DBBrokerTemplate {
     }
 
     @Override
-    public List<KeyMetadata> getKeysMetadata(String schemaName) throws SQLException {
+    public List<Key> getKeys(TapSchema tapSchema, String schemaName) throws SQLException {
         throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
     }
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java
similarity index 92%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java
index ca02f53..3be6652 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.io.Serializable;
 
@@ -33,6 +33,7 @@ public class PropertyModel implements Serializable {
     private static final long serialVersionUID = -3081516272534689428L;
 
     private String name;
+    private String description;
     private Class type;
     private Integer size;
     private boolean updatable;
@@ -45,6 +46,7 @@ public class PropertyModel implements Serializable {
     public PropertyModel(PropertyXMLModel propertyXMLModel) {
         try {
             name = propertyXMLModel.getName();
+            description = propertyXMLModel.getDescription();
             type = Class.forName(propertyXMLModel.getType());
             size = propertyXMLModel.getSize();
             updatable = propertyXMLModel.isUpdatable();
@@ -61,6 +63,10 @@ public class PropertyModel implements Serializable {
         return name;
     }
 
+    public String getDescription() {
+        return description;
+    }
+
     public Class getType() {
         return type;
     }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyXMLModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyXMLModel.java
similarity index 98%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyXMLModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyXMLModel.java
index 8558bf7..2746abf 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/PropertyXMLModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyXMLModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import javax.xml.bind.annotation.XmlElement;
 
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java
similarity index 88%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java
index a058342..892972a 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.io.Serializable;
 import java.util.HashMap;
@@ -36,14 +36,16 @@ public class TableModel implements Serializable {
 
     private final Map<String, PropertyModel> properties;
     private String name;
+    private String description;
 
     private TableModel() {
         this.properties = new HashMap<>();
     }
 
-    public TableModel(String name) {
+    public TableModel(String name, String description) {
         this();
         this.name = name;
+        this.description = description;
     }
 
     public String getName() {
@@ -57,4 +59,8 @@ public class TableModel implements Serializable {
     public PropertyModel get(String columnName) {
         return properties.get(columnName);
     }
+
+    public String getDescription() {
+        return description;
+    }
 }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableXMLModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java
similarity index 98%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableXMLModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java
index b0118b4..17848aa 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TableXMLModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.util.List;
 import javax.xml.bind.annotation.XmlAttribute;
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModel.java
similarity index 87%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModel.java
index 7c8ae31..9760e1b 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.io.Serializable;
 import java.util.HashMap;
@@ -36,20 +36,26 @@ public class TapSchemaModel implements Serializable {
 
     private final Map<String, TableModel> tables;
     private String version;
+    private String description;
 
     private TapSchemaModel() {
         tables = new HashMap<>();
     }
 
-    public TapSchemaModel(String version) {
+    public TapSchemaModel(String version, String description) {
         this();
         this.version = version;
+        this.description = description;
     }
 
     public String getVersion() {
         return version;
     }
 
+    public String getDescription() {
+        return description;
+    }
+
     public Map<String, TableModel> getTables() {
         return tables;
     }
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModels.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModels.java
similarity index 84%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModels.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModels.java
index 7ab8dc4..25fc5be 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaModels.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaModels.java
@@ -20,9 +20,11 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
 import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -49,22 +51,25 @@ public class TapSchemaModels {
             MODELS = new HashMap<>();
 
             for (TapSchemaXMLModel xmlModel : xmlModels.values()) {
-                TapSchemaModel model = new TapSchemaModel(xmlModel.getVersion());
+                TapSchemaModel model = new TapSchemaModel(xmlModel.getVersion(), xmlModel.getDescription());
                 loadTapSchemaModel(model, xmlModel, xmlModels);
                 MODELS.put(model.getVersion(), model);
             }
-        } catch (URISyntaxException e) {
+        } catch (IOException e) {
             throw new ExceptionInInitializerError(e);
         }
     }
 
-    private static Map<String, TapSchemaXMLModel> getXmlModels() throws URISyntaxException {
+    private static Map<String, TapSchemaXMLModel> getXmlModels() throws IOException {
         Map<String, TapSchemaXMLModel> xmlModels = new HashMap<>();
-        File modelsDirectory = new File(TapSchemaModels.class.getClassLoader().getResource("tap_schema").toURI());
-        for (File modelFile : modelsDirectory.listFiles()) {
-            TapSchemaXMLModel model = JAXB.unmarshal(modelFile, TapSchemaXMLModel.class);
-            xmlModels.put(model.getVersion(), model);
+
+        for (String modelFile : Tasman.XML_MODEL_FILES) {
+            try (InputStream in = TapSchemaModels.class.getClassLoader().getResourceAsStream(modelFile)) {
+                TapSchemaXMLModel model = JAXB.unmarshal(in, TapSchemaXMLModel.class);
+                xmlModels.put(model.getVersion(), model);
+            }
         }
+
         return xmlModels;
     }
 
@@ -74,7 +79,7 @@ public class TapSchemaModels {
             String tableName = tableXmlModel.getName();
             TableModel tableModel = model.get(tableName);
             if (tableModel == null) {
-                tableModel = new TableModel(tableName);
+                tableModel = new TableModel(tableName, tableXmlModel.getDescription());
             }
             for (PropertyXMLModel property : tableXmlModel.getAdd()) {
                 tableModel.getProperties().put(property.getName(), new PropertyModel(property));
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaXMLModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaXMLModel.java
similarity index 98%
rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaXMLModel.java
rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaXMLModel.java
index e320d16..dc561f8 100644
--- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/xmlmodel/TapSchemaXMLModel.java
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TapSchemaXMLModel.java
@@ -20,7 +20,7 @@
  * this program; if not, write to the Free Software Foundation, Inc., 51
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
-package it.inaf.ia2.tsm.xmlmodel;
+package it.inaf.ia2.tsm.model;
 
 import java.util.List;
 import javax.xml.bind.annotation.XmlAttribute;
diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/Tasman.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/Tasman.java
new file mode 100644
index 0000000..11fc66e
--- /dev/null
+++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/Tasman.java
@@ -0,0 +1,55 @@
+/*
+ * _____________________________________________________________________________
+ * 
+ * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of
+ * Trieste INAF - IA2 Italian Center for Astronomical Archives
+ * _____________________________________________________________________________
+ * 
+ * Copyright (C) 2017 Istituto Nazionale di Astrofisica
+ * 
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License Version 3 as published by the
+ * Free Software Foundation.
+ * 
+ * This program 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
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package it.inaf.ia2.tsm.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ *
+ * @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
+ */
+public class Tasman {
+
+    public static final String[] XML_MODEL_FILES;
+    public static final boolean ALLOWS_FICTITIOUS_KEYS;
+
+    static {
+        try (InputStream in = Tasman.class.getClassLoader().getResourceAsStream("core.properties")) {
+            Properties props = new Properties();
+            props.load(in);
+            String[] models = props.getProperty("models").split(",");
+            XML_MODEL_FILES = new String[models.length];
+            for (int i = 0; i < models.length; i++) {
+                String suffix = models[i];
+                XML_MODEL_FILES[i] = "tap_schema" + File.separator + "tap_schema-" + suffix + ".xml";
+            }
+
+            ALLOWS_FICTITIOUS_KEYS = Boolean.parseBoolean(props.getProperty("allow_fictitious_keys"));
+        } catch (IOException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+}
diff --git a/TASMAN-core/src/main/resources/core.properties b/TASMAN-core/src/main/resources/core.properties
new file mode 100644
index 0000000..d7dd188
--- /dev/null
+++ b/TASMAN-core/src/main/resources/core.properties
@@ -0,0 +1,9 @@
+## Configuration properties ##
+
+# List of supported TAP_SCHEMA models. These comma separated values are XML file
+# suffixes for model configurations.
+# (It is necessary to put this list here because, unfortunately, there is no
+# easy way to read an entire resource folder using the ClassLoader).
+models = 1,1-IA2,1_1
+
+allow_fictitious_keys = false
diff --git a/TASMAN-core/src/main/resources/tap_schema/tap_schema-1.xml b/TASMAN-core/src/main/resources/tap_schema/tap_schema-1.xml
index 89adc9c..26c5446 100644
--- a/TASMAN-core/src/main/resources/tap_schema/tap_schema-1.xml
+++ b/TASMAN-core/src/main/resources/tap_schema/tap_schema-1.xml
@@ -186,8 +186,6 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
                 <type>java.lang.String</type>
                 <size>64</size>
                 <updatable>true</updatable>
-                <key>key_id</key>
-                <nullable>false</nullable>
                 <description>unique key to join to TAP_SCHEMA.key_columns</description>
             </property>
             <property>
@@ -229,8 +227,6 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
                 <type>java.lang.String</type>
                 <size>64</size>
                 <updatable>true</updatable>
-                <key>key_id</key>
-                <nullable>false</nullable>
                 <description>key to join to TAP_SCHEMA.keys</description>
             </property>
             <property>
diff --git a/TASMAN-core/src/test/java/it/inaf/ia2/tsm/api/TestAll.java b/TASMAN-core/src/test/java/it/inaf/ia2/tsm/api/TestAll.java
index c85aaf4..6b67e26 100644
--- a/TASMAN-core/src/test/java/it/inaf/ia2/tsm/api/TestAll.java
+++ b/TASMAN-core/src/test/java/it/inaf/ia2/tsm/api/TestAll.java
@@ -43,9 +43,8 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -63,7 +62,7 @@ import org.slf4j.LoggerFactory;
  */
 public class TestAll {
 
-    private static final Logger log = LoggerFactory.getLogger(TestAll.class);
+    private static final Logger LOG = LoggerFactory.getLogger(TestAll.class);
 
     private static final int SCHEMAS_COUNT = 2; // minimum value: 2
     private static final int TABLES_COUNT = 3;
@@ -122,45 +121,62 @@ public class TestAll {
                 DatabaseType dbType = dbWrapper.getSourceDatabaseType();
 
                 // Removing keys between schema1 and schema0
-                if (dbType == DatabaseType.MYSQL) {
-                    try (ResultSet rs = statement.executeQuery("SHOW DATABASES WHERE `Database` = 'sch1'")) {
-                        // The constraint can be removed only if sch1 exists
-                        if (rs.next()) {
-                            statement.executeUpdate("ALTER TABLE sch1.table0 DROP FOREIGN KEY sch0table0id_constraint");
-                        }
+                if (null == dbType) {
+                    throw new UnsupportedOperationException("Database type " + dbType + " not supported");
+                } else {
+                    switch (dbType) {
+                        case MYSQL:
+                            try (ResultSet rs = statement.executeQuery("SHOW DATABASES WHERE `Database` = 'sch1'")) {
+                                // The constraint can be removed only if sch1 exists
+                                if (rs.next()) {
+                                    statement.executeUpdate("ALTER TABLE sch1.table0 DROP FOREIGN KEY sch0table0id_constraint");
+                                }
+                            }
+                            break;
+                        case POSTGRES:
+                            try (ResultSet rs = statement.executeQuery("SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'sch1'")) {
+                                // The constraint can be removed only if sch1 exists
+                                if (rs.next()) {
+                                    statement.executeUpdate("ALTER TABLE sch1.table0 DROP CONSTRAINT sch0table0id_constraint");
+                                }
+                            }
+                            break;
+                        default:
+                            throw new UnsupportedOperationException("Database type " + dbType + " not supported");
                     }
-                } else if (dbType == DatabaseType.POSTGRES) {
-                    try (ResultSet rs = statement.executeQuery("SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'sch1'")) {
-                        // The constraint can be removed only if sch1 exists
-                        if (rs.next()) {
-                            statement.executeUpdate("ALTER TABLE sch1.table0 DROP CONSTRAINT sch0table0id_constraint");
+
+                    for (int i = 0; i < SCHEMAS_COUNT; i++) {
+                        switch (dbType) {
+                            case MYSQL:
+                                statement.executeUpdate("DROP DATABASE IF EXISTS sch" + i);
+                                break;
+                            case POSTGRES:
+                                statement.executeUpdate("DROP SCHEMA IF EXISTS sch" + i + " CASCADE");
+                                break;
+                            default:
+                                throw new UnsupportedOperationException("Database type " + dbType + " not supported");
                         }
                     }
-                } else {
-                    throw new UnsupportedOperationException("Database type " + dbType + " not supported");
                 }
-
-                for (int i = 0; i < SCHEMAS_COUNT; i++) {
-                    if (dbType == DatabaseType.MYSQL) {
-                        statement.executeUpdate("DROP DATABASE IF EXISTS sch" + i);
-                    } else if (dbType == DatabaseType.POSTGRES) {
-                        statement.executeUpdate("DROP SCHEMA IF EXISTS sch" + i + " CASCADE");
-                    } else {
+                try (Connection tapSchemaConnection = dbWrapper.getTapSchemaConnection();
+                        Statement stat = tapSchemaConnection.createStatement()) {
+                    dbType = dbWrapper.getTapSchemaDatabaseType();
+                    if (null == dbType) {
                         throw new UnsupportedOperationException("Database type " + dbType + " not supported");
+                    } else {
+                        switch (dbType) {
+                            case MYSQL:
+                                stat.executeUpdate("DROP DATABASE IF EXISTS test_tap_schema");
+                                break;
+                            case POSTGRES:
+                                stat.executeUpdate("DROP SCHEMA IF EXISTS test_tap_schema CASCADE");
+                                break;
+                            default:
+                                throw new UnsupportedOperationException("Database type " + dbType + " not supported");
+                        }
                     }
                 }
             }
-            try (Connection tapSchemaConnection = dbWrapper.getTapSchemaConnection();
-                    Statement statement = tapSchemaConnection.createStatement()) {
-                DatabaseType dbType = dbWrapper.getTapSchemaDatabaseType();
-                if (dbType == DatabaseType.MYSQL) {
-                    statement.executeUpdate("DROP DATABASE IF EXISTS test_tap_schema");
-                } else if (dbType == DatabaseType.POSTGRES) {
-                    statement.executeUpdate("DROP SCHEMA IF EXISTS test_tap_schema CASCADE");
-                } else {
-                    throw new UnsupportedOperationException("Database type " + dbType + " not supported");
-                }
-            }
         }
     }
 
@@ -175,34 +191,41 @@ public class TestAll {
 
                 try (Statement statement = connection.createStatement()) {
 
-                    if (dbType == DatabaseType.MYSQL) {
-                        for (int i = 0; i < SCHEMAS_COUNT; i++) {
-                            statement.executeUpdate("CREATE DATABASE sch" + i);
-                            for (int j = 0; j < TABLES_COUNT; j++) {
-                                statement.executeUpdate("CREATE TABLE sch" + i + ".table" + j + " (\n"
-                                        + "id INT PRIMARY KEY AUTO_INCREMENT,\n"
-                                        + "value1 VARCHAR(255),\n"
-                                        + "value2 FLOAT\n"
-                                        + ");");
-                            }
-                        }
-                    } else if (dbType == DatabaseType.POSTGRES) {
-                        for (int i = 0; i < SCHEMAS_COUNT; i++) {
-                            statement.executeUpdate("CREATE SCHEMA sch" + i);
-                            for (int j = 0; j < TABLES_COUNT; j++) {
-                                statement.executeUpdate("CREATE TABLE sch" + i + ".table" + j + " (\n"
-                                        + "id BIGSERIAL PRIMARY KEY,\n"
-                                        + "value1 VARCHAR(255),\n"
-                                        + "value2 FLOAT\n"
-                                        + ");");
-                            }
-                        }
-                    } else {
+                    if (null == dbType) {
                         throw new UnsupportedOperationException("Database type " + dbType + " not supported");
+                    } else {
+                        switch (dbType) {
+                            case MYSQL:
+                                for (int i = 0; i < SCHEMAS_COUNT; i++) {
+                                    statement.executeUpdate("CREATE DATABASE sch" + i);
+                                    for (int j = 0; j < TABLES_COUNT; j++) {
+                                        statement.executeUpdate("CREATE TABLE sch" + i + ".table" + j + " (\n"
+                                                + "id INT PRIMARY KEY AUTO_INCREMENT,\n"
+                                                + "value1 VARCHAR(255),\n"
+                                                + "value2 FLOAT\n"
+                                                + ");");
+                                    }
+                                }
+                                break;
+                            case POSTGRES:
+                                for (int i = 0; i < SCHEMAS_COUNT; i++) {
+                                    statement.executeUpdate("CREATE SCHEMA sch" + i);
+                                    for (int j = 0; j < TABLES_COUNT; j++) {
+                                        statement.executeUpdate("CREATE TABLE sch" + i + ".table" + j + " (\n"
+                                                + "id BIGSERIAL PRIMARY KEY,\n"
+                                                + "value1 VARCHAR(255),\n"
+                                                + "value2 FLOAT\n"
+                                                + ");");
+                                    }
+                                }
+                                break;
+                            default:
+                                throw new UnsupportedOperationException("Database type " + dbType + " not supported");
+                        }
                     }
                 }
 
-                log.info("dbs created");
+                LOG.info("dbs created");
 
                 try (Statement statement = connection.createStatement()) {
                     for (int j = 0; j < TABLES_COUNT - 1; j++) {
@@ -235,62 +258,40 @@ public class TestAll {
         }
     }
 
-    @Test
-    public void test1() throws Exception {
-
-        setUpTestingDatabases();
-
-        for (DBWrapper dbWrapper : dbWrappers) {
-            TapSchema tapSchema = new TapSchema("1.0", dbWrapper, "test_tap_schema", false);
-            tapSchema.save();
+    private boolean checkKey(Key key, String fromTableCompleteName, String[] fromColumns, String targetTableCompleteName, String[] targetColumns, boolean isVisible) {
+        if (!fromTableCompleteName.equals(key.getFromTableCompleteName())) {
+            return false;
+        }
+        if (!targetTableCompleteName.equals(key.getTargetTableCompleteName())) {
+            return false;
         }
-    }
-
-//
-//    private boolean allKeysHaveDifferentId(TapSchema tapSchema) {
-//        boolean differentKeySameId = false;
-//        Map<String, Key> keys = new HashMap<>();
-//
-//        for (Key key : ((TapSchema) tapSchema).getAllKeys()) {
-//            if (key.getId() != null) {
-//                if (keys.get(key.getId()) != null && !key.equals(keys.get(key.getId()))) {
-//                    differentKeySameId = true;
-//                }
-//                keys.put(key.getId(), key);
-//            }
-//        }
-//
-//        if (differentKeySameId) {
-//            log.debug("Found different keys with the same key_id!");
-//            for (Key key : ((TapSchema) tapSchema).getAllKeys()) {
-//                log.debug(key.toString());
-//            }
-//        }
-//
-//        return !differentKeySameId;
-//    }
-//
-    private void checkKey(Key key, String fromTableCompleteName, String[] fromColumns, String targetTableCompleteName, String[] targetColumns, boolean isVisible) {
-        assertEquals(fromTableCompleteName, key.getFromTableCompleteName());
-        assertEquals(targetTableCompleteName, key.getTargetTableCompleteName());
         for (int i = 0; i < key.getKeyColumns().size(); i++) {
             KeyColumn keyColumn = key.getKeyColumns().get(i);
-            assertEquals(fromColumns[i], keyColumn.getFromColumn());
-            assertEquals(targetColumns[i], keyColumn.getTargetColumn());
+            if (!fromColumns[i].equals(keyColumn.getFromColumn())) {
+                return false;
+            }
+            if (!targetColumns[i].equals(keyColumn.getTargetColumn())) {
+                return false;
+            }
+        }
+        if (isVisible != key.isVisible()) {
+            return false;
         }
-        assertEquals(isVisible, key.isVisible());
         for (KeyColumn keyColumn : key.getKeyColumns()) {
-            assertEquals(key.getId(), keyColumn.getKeyId());
+            if (!Objects.equals(key.getId(), keyColumn.getKeyId())) {
+                return false;
+            }
         }
+        return true;
     }
 
-    private void checkKey(Key key, String fromTableCompleteName, String fromColumn, String targetTableCompleteName, String targetColumn, boolean isVisible) {
-        checkKey(key, fromTableCompleteName, new String[]{fromColumn}, targetTableCompleteName, new String[]{targetColumn}, isVisible);
+    private boolean checkKey(Key key, String fromTableCompleteName, String fromColumn, String targetTableCompleteName, String targetColumn, boolean isVisible) {
+        return checkKey(key, fromTableCompleteName, new String[]{fromColumn}, targetTableCompleteName, new String[]{targetColumn}, isVisible);
     }
 
     @Test
     public void createNewAndUpdate() throws SQLException {
-        log.info("TEST createNewAndUpdate STARTED");
+        LOG.info("TEST createNewAndUpdate STARTED");
 
         try {
             removeTestingDatabases();
@@ -309,11 +310,12 @@ public class TestAll {
                 Schema sch0 = tapSchema.addChild("sch0");
                 assertEquals(Status.ADDED_NOT_PERSISTED, sch0.getStatus());
 
-//                Set<Key> allKeys = tapSchema.getAllKeys();
-//                log.debug("ALL keys:");
-//                for (Key key : allKeys) {
-//                    log.debug(key.toString());
-//                }
+                Set<Key> allKeys = tapSchema.getAllKeys();
+                LOG.debug("ALL keys:");
+                for (Key key : allKeys) {
+                    LOG.debug(key.toString());
+                }
+
                 // In the testing schemas each numbered table references the id 
                 // of the previous table, except for the first table, so there
                 // should be "TABLES_COUNT - 1" keys for the numbered tables.
@@ -322,20 +324,20 @@ public class TestAll {
                 // - sch1.table0.sch0table0id -> sch0.table0.id
                 // - sch0.table_y.(idy1, idy2) -> sch0.table_x.(idyx, idx2)
                 // so we check for TABLES_COUNT + 2.
-//                assertEquals(TABLES_COUNT + 2, allKeys.size());
-//
-//                // Checking that keys information has been filled correctly.
-//                for (Key schemaKey : allKeys) {
-//                    assertFalse(schemaKey.isVisible());
-//                    assertNull(schemaKey.getId());
-//                    assertEquals(schemaKey.getFromTableCompleteName(), schemaKey.getFromSchemaName() + "." + schemaKey.getFromTableSimpleName());
-//                    assertEquals(schemaKey.getTargetTableCompleteName(), schemaKey.getTargetSchemaName() + "." + schemaKey.getTargetTableSimpleName());
-//                    assertTrue(schemaKey.getKeyColumns().size() >= 1);
-//                    for (KeyColumn keyColumn : schemaKey.getKeyColumns()) {
-//                        assertNotNull(keyColumn.getFromColumn());
-//                        assertNotNull(keyColumn.getTargetColumn());
-//                    }
-//                }
+                assertEquals(TABLES_COUNT + 2, allKeys.size());
+
+                // Checking that keys information has been filled correctly.
+                for (Key schemaKey : allKeys) {
+                    assertFalse(schemaKey.isVisible());
+                    assertNull(schemaKey.getId());
+                    assertEquals(schemaKey.getFromTableCompleteName(), schemaKey.getFromSchemaName() + "." + schemaKey.getFromTableSimpleName());
+                    assertEquals(schemaKey.getTargetTableCompleteName(), schemaKey.getTargetSchemaName() + "." + schemaKey.getTargetTableSimpleName());
+                    assertTrue(schemaKey.getKeyColumns().size() >= 1);
+                    for (KeyColumn keyColumn : schemaKey.getKeyColumns()) {
+                        assertNotNull(keyColumn.getFromColumn());
+                        assertNotNull(keyColumn.getTargetColumn());
+                    }
+                }
                 /////////////////////////////////////
                 //         ADDING A TABLE          //
                 /////////////////////////////////////
@@ -366,11 +368,11 @@ public class TestAll {
 
                 assertTrue(tapSchema.getVisibileKeys().isEmpty());
                 sch0table1.addChild("table0_id");
-                assertEquals(1, tapSchema.getVisibileKeys());
+                assertEquals(1, tapSchema.getVisibileKeys().size());
 
                 // Check if key and its columns have been properly initialized
                 Key k1 = tapSchema.getVisibileKeys().get(0);
-                checkKey(k1, "sch0.table1", "table0_id", "sch0.table0", "id", true);
+                assertTrue(checkKey(k1, "sch0.table1", "table0_id", "sch0.table0", "id", true));
 
                 // Removing sch0.table1
                 sch0.removeChild("table1");
@@ -383,8 +385,7 @@ public class TestAll {
                 //
                 // Adding sch1
                 Schema sch1 = tapSchema.addChild("sch1");
-//                allKeys = ((TapSchema) tapSchema).getAllKeys();
-//                assertEquals(5, allKeys.size());
+                assertEquals(5, allKeys.size());
 
                 // Adding sch1.table0
                 Table sch1table0 = sch1.addChild("table0");
@@ -393,105 +394,52 @@ public class TestAll {
                 sch1table0.addChild("sch0table0id"); // sch1.table0.sch0table0id -> sch0.table0.it obtains keyId = "1"
                 sch0table0.addChild("sch1table0id");// sch0.table0.sch1table0id -> sch1.table0.it obtains keyId = "2"
 
-//                assertEquals(0, sch0table1.getVisibleFromKeys().size());
-//                assertEquals(1, sch0table0.getVisibleFromKeys().size());
-//                assertEquals(1, sch0table0.getVisibleTargetKeys().size());
-//                assertEquals(1, sch1table0.getVisibleFromKeys().size());
-//                assertEquals(1, sch1table0.getVisibleTargetKeys().size());
-//                for (Key key : allKeys) {
-//                    if (key.getId() == null) {
-//                        assertFalse(key.isVisible());
-//                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false);
-//                                break;
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                        }
-//                    }
-//                }
-//                assertTrue(allKeysHaveDifferentId(tapSchema));
+                assertEquals(2, tapSchema.getVisibileKeys().size());
+
+                for (Key key : tapSchema.getVisibileKeys()) {
+                    assertTrue(
+                            checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false)
+                            || checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true)
+                            || checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true)
+                    );
+                }
+
                 // Removing sch1
                 tapSchema.removeChild("sch1");
                 assertEquals(Status.REMOVED_NOT_PERSISTED, sch1.getStatus());
-//                assertTrue(sch0table0.getVisibleTargetKeys().isEmpty());
+                assertEquals(0, tapSchema.getVisibileKeys().size());
 
                 // Case 2B: Re-adding sch1
                 // sch1.table0 has not been removed from its schema, so the keys
                 // should be re-added.
                 tapSchema.addChild("sch1");
                 assertEquals(Status.ADDED_NOT_PERSISTED, sch1.getStatus());
-//                assertEquals(1, sch0table0.getVisibleTargetKeys().size());
-//                assertEquals(1, sch1table0.getVisibleFromKeys().size());
+                assertEquals(2, tapSchema.getVisibileKeys().size());
 
-//                for (Key key : allKeys) {
-//                    if (key.getId() == null) {
-//                        assertFalse(key.isVisible());
-//                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false);
-//                                break;
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                        }
-//                    }
-//                }
                 //
                 // CASE 3: foreign key with multiple columns
                 //
                 Table table_x = sch0.addChild("table_x");
                 Table table_y = sch0.addChild("table_y");
+                assertEquals(2, tapSchema.getVisibileKeys().size());
 
-//                assertTrue(table_x.getVisibleFromKeys().isEmpty());
-//                assertTrue(table_x.getVisibleTargetKeys().isEmpty());
-//                assertTrue(table_y.getVisibleFromKeys().isEmpty());
-//                assertTrue(table_y.getVisibleTargetKeys().isEmpty());
                 table_x.addChild("idx1");
                 table_x.addChild("idx2");
                 table_y.addChild("idy1");
+                assertEquals(2, tapSchema.getVisibileKeys().size());
 
-//                assertTrue(table_x.getVisibleFromKeys().isEmpty());
-//                assertTrue(table_x.getVisibleTargetKeys().isEmpty());
-//                assertTrue(table_y.getVisibleFromKeys().isEmpty());
-//                assertTrue(table_y.getVisibleTargetKeys().isEmpty());
                 table_y.addChild("idy2");
+                assertEquals(3, tapSchema.getVisibileKeys().size());
+
+                for (Key key : tapSchema.getVisibileKeys()) {
+                    assertTrue(
+                            checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false)
+                            || checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true)
+                            || checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true)
+                            || checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true)
+                    );
+                }
 
-//                assertEquals(1, table_y.getVisibleFromKeys().size());
-//                assertEquals(1, table_x.getVisibleTargetKeys().size());
-//                assertTrue(table_x.getVisibleFromKeys().isEmpty());
-//                assertTrue(table_y.getVisibleTargetKeys().isEmpty());
-//                for (Key key : allKeys) {
-//                    if (key.getId() == null) {
-//                        assertFalse(key.isVisible());
-//                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false);
-//                                break;
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                            case "4":
-//                                checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true);
-//                                break;
-//                        }
-//                    }
-//                }
-//
-//                assertTrue(allKeysHaveDifferentId(tapSchema));
                 /////////////////////////////////////
                 //              SAVE               //
                 /////////////////////////////////////
@@ -500,30 +448,6 @@ public class TestAll {
                 Table sch0table2 = sch0.addChild("table2");
                 sch0table2.addChild("table1_id");
 
-//                for (Key key : allKeys) {
-//                    if (key.getId() == null) {
-//                        assertFalse(key.isVisible());
-//                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", true);
-//                                break;
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                            case "4":
-//                                checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true);
-//                                break;
-//                            case "5":
-//                                checkKey(key, "sch0.table2", "table1_id", "sch0.table1", "id", true);
-//                                break;
-//                        }
-//                    }
-//                }
-//                assertTrue(allKeysHaveDifferentId(tapSchema));
                 UpdateOperations operations = new UpdateOperations(tapSchema);
                 assertEquals(2, operations.getSchemasToAdd().size());
                 assertEquals(6, operations.getTablesToAdd().size());
@@ -531,15 +455,13 @@ public class TestAll {
                 assertEquals(5, operations.getKeysToAdd().size());
 
                 tapSchema.save();
-                assertFalse(new UpdateOperations(tapSchema).getHasOperations());
-//                assertTrue(allKeysHaveDifferentId(tapSchema));
+                operations = new UpdateOperations(tapSchema);
+                assertFalse(operations.getHasOperations());
 
                 // reloading
-                log.debug("----- Reloading saved TAP_SCHEMA -----");
-//                tapSchema = TapSchemaFactory.getTapSchema(TapSchemaVersion.TAP_SCHEMA_1_IA2, dbWrapper, "test_tap_schema", true);
-//                allKeys = ((TapSchema) tapSchema).getAllKeys();
-//                assertTrue(allKeysHaveDifferentId(tapSchema));
-                log.debug(tapSchema.toString());
+                LOG.debug("----- Reloading saved TAP_SCHEMA -----");
+                tapSchema = new TapSchema("1.0", dbWrapper, "test_tap_schema", true);
+                LOG.debug(tapSchema.toString());
 
                 assertNotNull(sch0 = tapSchema.getChild("sch0", Status.ADDED_PERSISTED));
                 assertNotNull(sch1 = tapSchema.getChild("sch1", Status.ADDED_PERSISTED));
@@ -565,43 +487,16 @@ public class TestAll {
 //                    if (key.getId() == null) {
 //                        assertFalse(key.isVisible());
 //                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", true);
-//                                break;
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                            case "4":
-//                                checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true);
-//                                break;
-//                            case "5":
-//                                checkKey(key, "sch0.table2", "table1_id", "sch0.table1", "id", true);
-//                                break;
-//                        }
+//                        assertTrue(
+//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", true)
+//                                || checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true)
+//                                || checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true)
+//                                || checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true)
+//                                || checkKey(key, "sch0.table2", "table1_id", "sch0.table1", "id", true)
+//                        );
 //                    }
 //                }
-//                List<Key> sch0table1FromKeys = sch0table1.getVisibleFromKeys();
-//                assertEquals(1, sch0table1FromKeys.size());
-//                assertEquals(1, sch0table1.getVisibleTargetKeys().size());
-//
                 sch0.removeChild("table1");
-//                assertEquals(0, sch0table1.getVisibleFromKeys().size());
-//
-//                for (Key key : allKeys) {
-//                    if (key.getId() == null) {
-//                        assertFalse(key.isVisible());
-//                    } else {
-//                        switch (key.getId()) {
-//                            case "1":
-//                                checkKey(key, "sch0.table1", "table0_id", "sch0.table0", "id", false);
-//                                break;
-//                        }
-//                    }
-//                }
 
                 operations = new UpdateOperations(tapSchema);
                 assertFalse(operations.getHasEntitiesToUpdate());
@@ -612,14 +507,14 @@ public class TestAll {
                 assertEquals(2, operations.getKeysToRemove().size());
 
                 tapSchema.save();
-                log.debug(tapSchema.toString());
-                assertFalse(new UpdateOperations(tapSchema).getHasOperations());
+                LOG.debug(tapSchema.toString());
+                operations = new UpdateOperations(tapSchema);
+                assertFalse(operations.getHasOperations());
 
                 // reloading
-                log.debug("----- Reloading saved TAP_SCHEMA -----");
-                tapSchema = new TapSchema("1.0", dbWrapper, "test_tap_schema", false);
-//                allKeys = ((TapSchema) tapSchema).getAllKeys();
-                log.debug(tapSchema.toString());
+                LOG.debug("----- Reloading saved TAP_SCHEMA -----");
+                tapSchema = new TapSchema("1.0", dbWrapper, "test_tap_schema", true);
+                LOG.debug(tapSchema.toString());
 
                 assertNotNull(sch0 = tapSchema.getChild("sch0", Status.ADDED_PERSISTED));
                 assertNotNull(sch1 = tapSchema.getChild("sch1", Status.ADDED_PERSISTED));
@@ -643,20 +538,12 @@ public class TestAll {
 //                        assertFalse(key.isVisible());
 //                    } else {
 //                        assertNotNull(key.getOriginalValue(Key.ID_KEY, String.class)); // for reloaded keys
-//                        switch (key.getId()) {
-//                            case "2":
-//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true);
-//                                break;
-//                            case "3":
-//                                checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true);
-//                                break;
-//                            case "4":
-//                                checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true);
-//                                break;
-//                            case "5":
-//                                checkKey(key, "sch0.table2", "table1_id", "sch0.table1", "id", true);
-//                                break;
-//                        }
+//                        assertTrue(
+//                                checkKey(key, "sch1.table0", "sch0table0id", "sch0.table0", "id", true)
+//                                || checkKey(key, "sch0.table0", "sch1table0id", "sch1.table0", "id", true)
+//                                || checkKey(key, "sch0.table_y", new String[]{"idy1", "idy2"}, "sch0.table_x", new String[]{"idx1", "idx2"}, true)
+//                                || checkKey(key, "sch0.table2", "table1_id", "sch0.table1", "id", true)
+//                        );
 //                    }
 //                }
                 // Test adding ficitious key
@@ -706,7 +593,7 @@ public class TestAll {
                     tapSchema = (TapSchema) in.readObject();
                 }
 
-                log.debug(tapSchema.toString());
+                LOG.debug(tapSchema.toString());
             }
         }
     }
diff --git a/TASMAN-webapp/pom.xml b/TASMAN-webapp/pom.xml
index 2afaa32..9038a68 100644
--- a/TASMAN-webapp/pom.xml
+++ b/TASMAN-webapp/pom.xml
@@ -4,7 +4,7 @@
 
     <groupId>it.inaf.ia2.tap</groupId>
     <artifactId>tasman-webapp</artifactId>
-    <version>1.1.0</version>
+    <version>1.2.0</version>
     <packaging>war</packaging>
 
     <name>tasman-webapp</name>
@@ -88,7 +88,7 @@
         <dependency>
             <groupId>it.inaf.ia2.tap</groupId>
             <artifactId>tasman-core</artifactId>
-            <version>1.1.0</version>
+            <version>1.2.0</version>
         </dependency>
         <dependency>
             <groupId>ari.ucidy</groupId>
diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java
index abf6235..81b1423 100644
--- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java
+++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/ConsistencyChecksBean.java
@@ -22,8 +22,8 @@
  */
 package it.inaf.ia2.tsm.webapp;
 
+import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.datalayer.DBWrapper;
-import it.inaf.ia2.tsm.api.contract.TapSchema;
 import java.io.Serializable;
 import java.sql.SQLException;
 import javax.inject.Inject;
diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java
index 75d0987..1a2f655 100644
--- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java
+++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/SchemaSelectionBean.java
@@ -22,12 +22,10 @@
  */
 package it.inaf.ia2.tsm.webapp;
 
-import it.inaf.ia2.tsm.api.contract.TapSchema;
-import it.inaf.ia2.tsm.api.contract.TapSchemaVersion;
+import it.inaf.ia2.tsm.TapSchema;
+import it.inaf.ia2.tsm.datalayer.DBBroker;
+import it.inaf.ia2.tsm.datalayer.DBBrokerFactory;
 import it.inaf.ia2.tsm.datalayer.DBWrapper;
-import it.inaf.ia2.tsm.Dao;
-import it.inaf.ia2.tsm.DaoSchema;
-import it.inaf.ia2.tsm.TapSchemaFactory;
 import java.io.Serializable;
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -92,7 +90,8 @@ public class SchemaSelectionBean implements Serializable {
 
             // Loading all schemas of the source database
             try {
-                allSchemas = DaoSchema.getAllSchemasNames(dbWrapper.getSourceDataSource(), dbWrapper.getSourceDatabaseType());
+            DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getSourceDataSourceWrapper());
+                allSchemas = broker.getAllSchemaNames();
                 setSelectedSchemas(new ArrayList<String>());
             } catch (SQLException e) {
                 throw new RuntimeException(e);
@@ -100,7 +99,8 @@ public class SchemaSelectionBean implements Serializable {
 
             // Loading all schemas of the TAP_SCHEMA database
             try {
-                allTAPSchemas = Dao.getAllTAPSchemasNames(dbWrapper, DaoSchema.getAllSchemasNames(dbWrapper.getTapSchemaDataSource(), dbWrapper.getTapSchemaDatabaseType()));
+            DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper());
+                allTAPSchemas = broker.getAllTAPSchemaNames(allSchemas);
 
                 if (!allTAPSchemas.isEmpty()) {
                     this.selectedTAPSchema = allTAPSchemas.get(0);
@@ -113,7 +113,8 @@ public class SchemaSelectionBean implements Serializable {
     }
 
     private void loadExposedSchemas() throws SQLException {
-        List<String> schemas = Dao.getExposedSchemas(dbWrapper, selectedTAPSchema);
+        DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper());
+        List<String> schemas = broker.getExposedSchemas(selectedTAPSchema);
         exposedSchemas = "";
         for (int i = 0; i < schemas.size(); i++) {
             exposedSchemas += schemas.get(i);
@@ -148,9 +149,9 @@ public class SchemaSelectionBean implements Serializable {
     }
 
     public void setSelectedTAPSchema(String selectedTAPSchema) {
-        this.selectedTAPSchema = selectedTAPSchema;        
+        this.selectedTAPSchema = selectedTAPSchema;
     }
-    
+
     public void selectedTAPSchemaChanged() {
         try {
             loadExposedSchemas();
@@ -188,11 +189,11 @@ public class SchemaSelectionBean implements Serializable {
             @Override
             public void run() {
                 try {
-                    loadedTapSchema = TapSchemaFactory.getTapSchema(TapSchemaVersion.TAP_SCHEMA_1_IA2, dbWrapper, selectedTAPSchema, true);
+                    loadedTapSchema = new TapSchema("1.0-IA2", dbWrapper, selectedTAPSchema, true);
                 } catch (Throwable e) {
                     LOG.error("Exception caught", e);
                     loadingError = e.getMessage();
-                    if(loadingError == null) {
+                    if (loadingError == null) {
                         loadingError = e.getClass().getCanonicalName();
                     }
                 }
@@ -211,7 +212,7 @@ public class SchemaSelectionBean implements Serializable {
             @Override
             public void run() {
                 try {
-                    loadedTapSchema = TapSchemaFactory.getTapSchema(TapSchemaVersion.TAP_SCHEMA_1_IA2, dbWrapper, tapSchemaName, false);
+                    loadedTapSchema = new TapSchema("1.0-IA2", dbWrapper, tapSchemaName, false);
                     for (String schemaName : selectedSchemas) {
                         loadedTapSchema.addChild(schemaName);
                     }
@@ -270,7 +271,7 @@ public class SchemaSelectionBean implements Serializable {
     public String getLoadingError() {
         return loadingError;
     }
-    
+
     public TapSchema getLoadedTapSchema() {
         return loadedTapSchema;
     }
diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java
index 5a8c784..5faedbe 100644
--- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java
+++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java
@@ -22,17 +22,17 @@
  */
 package it.inaf.ia2.tsm.webapp;
 
+import it.inaf.ia2.tsm.ChildEntity;
+import it.inaf.ia2.tsm.Column;
 import it.inaf.ia2.tsm.webapp.env.CustomPartialResponseWriter;
 import it.inaf.ia2.tsm.webapp.env.JSUpdateHandler;
-import it.inaf.ia2.tsm.api.contract.ChildEntity;
-import it.inaf.ia2.tsm.api.contract.Column;
 import it.inaf.ia2.tsm.EntitiesContainer;
-import it.inaf.ia2.tsm.api.contract.Key;
-import it.inaf.ia2.tsm.api.contract.KeyColumn;
-import it.inaf.ia2.tsm.api.contract.Schema;
+import it.inaf.ia2.tsm.Key;
+import it.inaf.ia2.tsm.KeyColumn;
+import it.inaf.ia2.tsm.Schema;
 import it.inaf.ia2.tsm.Status;
-import it.inaf.ia2.tsm.api.contract.Table;
-import it.inaf.ia2.tsm.api.contract.TapSchema;
+import it.inaf.ia2.tsm.Table;
+import it.inaf.ia2.tsm.TapSchema;
 import it.inaf.ia2.tsm.TapSchemaEntity;
 import it.inaf.ia2.tsm.UpdateOperations;
 import java.io.Serializable;
@@ -229,7 +229,7 @@ public class TapSchemaEditingBean implements Serializable {
         if (selectedColumn == null) {
             voUnitValidator = new VOUnitValidator(null);
         } else {
-            voUnitValidator = new VOUnitValidator(selectedColumn.getUnit());
+            voUnitValidator = new VOUnitValidator(selectedColumn.getValue("unit", String.class));
         }
     }
 
@@ -305,9 +305,9 @@ public class TapSchemaEditingBean implements Serializable {
         if (!FacesContext.getCurrentInstance().isValidationFailed()) {
 
             if (searchUCDDialog.isManualInsertion()) {
-                selectedColumn.setUCD(searchUCDDialog.getUCDManualText());
+                selectedColumn.setValue("ucd", searchUCDDialog.getUCDManualText());
             } else {
-                selectedColumn.setUCD(searchUCDDialog.getSelectedUCD());
+                selectedColumn.setValue("ucd", searchUCDDialog.getSelectedUCD());
             }
 
             // New UCD is set and we can notify the client to close the UCD Search modal dialog.
@@ -327,7 +327,7 @@ public class TapSchemaEditingBean implements Serializable {
 
     public void openUCDDialog() throws Exception {
         searchUCDDialog.setDefault();
-        String description = selectedColumn.getDescription();
+        String description = selectedColumn.getValue("description", String.class);
         if (description != null && !description.isEmpty()) {
             searchUCDDialog.setDescription(description);
             searchUCDDialog.search();
diff --git a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml
index 501fec0..cb7d6c0 100644
--- a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml
+++ b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml
@@ -106,7 +106,7 @@
                                         <h:inputText 
                                             id="schema_utype"
                                             class="form-control #{tapSchemaEditing.selectedSchema.isChanged('utype') ? 'changed' : ''}"
-                                            value="#{tapSchemaEditing.selectedSchema.utype}">
+                                            value="#{tapSchemaEditing.selectedSchema.getProperty('utype').value}">
                                             <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                             <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedSchema, 'utype')}" onevent="TSM.textInputChanged" />
                                         </h:inputText>
@@ -118,7 +118,7 @@
                                         <h:inputText 
                                             id="schema_description"
                                             class="form-control #{tapSchemaEditing.selectedSchema.isChanged('description') ? 'changed' : ''}"
-                                            value="#{tapSchemaEditing.selectedSchema.description}">
+                                            value="#{tapSchemaEditing.selectedSchema.getProperty('description').value}">
                                             <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                             <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedSchema, 'description')}" onevent="TSM.textInputChanged" />
                                         </h:inputText>
@@ -174,7 +174,7 @@
                                                         <h:inputText 
                                                             id="table_utype"
                                                             class="form-control #{tapSchemaEditing.selectedTable.isChanged('utype') ? 'changed' : ''}"
-                                                            value="#{tapSchemaEditing.selectedTable.utype}">
+                                                            value="#{tapSchemaEditing.selectedTable.getProperty('utype').value}">
                                                             <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                                             <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedTable, 'utype')}" onevent="TSM.textInputChanged" />
                                                         </h:inputText>
@@ -186,7 +186,7 @@
                                                         <h:inputText 
                                                             id="table_description"
                                                             class="form-control #{tapSchemaEditing.selectedTable.isChanged('description') ? 'changed' : ''}"
-                                                            value="#{tapSchemaEditing.selectedTable.description}">
+                                                            value="#{tapSchemaEditing.selectedTable.getProperty('description').value}">
                                                             <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                                             <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedTable, 'description')}" onevent="TSM.textInputChanged" />
                                                         </h:inputText>
@@ -261,13 +261,13 @@
                                                             <div class="col-xs-6">
                                                                 <div class="form-group">
                                                                     <label for="datatype" class="control-label">Datatype:</label>
-                                                                    <span>#{tapSchemaEditing.selectedColumn.datatype}</span>
+                                                                    <span>#{tapSchemaEditing.selectedColumn.getProperty('datatype').value}</span>
                                                                 </div>
                                                             </div>
                                                             <div class="col-xs-6">
                                                                 <div class="form-group">
                                                                     <label for="size" class="control-label">Size:</label>
-                                                                    <span>#{tapSchemaEditing.selectedColumn.size}</span>
+                                                                    <span>#{tapSchemaEditing.selectedColumn.getProperty('size').value}</span>
                                                                 </div>
                                                             </div>
                                                         </div>
@@ -276,7 +276,7 @@
                                                                 <div class="checkbox">
                                                                     <label>
                                                                         <h:selectBooleanCheckbox 
-                                                                            value="#{tapSchemaEditing.selectedColumn.std}"
+                                                                            value="#{tapSchemaEditing.selectedColumn.getProperty('std').value}"
                                                                             class="#{tapSchemaEditing.selectedColumn.isChanged('std') ? 'changed' : ''}">
                                                                             <f:ajax execute="@form" render="@this" />
                                                                         </h:selectBooleanCheckbox>
@@ -288,7 +288,7 @@
                                                                 <div class="checkbox">
                                                                     <label>
                                                                         <h:selectBooleanCheckbox 
-                                                                            value="#{tapSchemaEditing.selectedColumn.principal}"
+                                                                            value="#{tapSchemaEditing.selectedColumn.getProperty('principal').value}"
                                                                             class="#{tapSchemaEditing.selectedColumn.isChanged('principal') ? 'changed' : ''}">
                                                                             <f:ajax execute="@form" render="@this" />
                                                                         </h:selectBooleanCheckbox>
@@ -302,7 +302,7 @@
                                                             <h:inputText 
                                                                 id="column_utype"
                                                                 class="form-control #{tapSchemaEditing.selectedColumn.isChanged('utype') ? 'changed' : ''}"
-                                                                value="#{tapSchemaEditing.selectedColumn.utype}">
+                                                                value="#{tapSchemaEditing.selectedColumn.getProperty('utype').value}">
                                                                 <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                                                 <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'utype')}" onevent="TSM.textInputChanged" />
                                                             </h:inputText>
@@ -310,7 +310,7 @@
                                                         <div class="form-group">
                                                             <label for=":main:column_ucd" class="control-label">UCD:</label>
                                                             <h:commandLink action="#{tapSchemaEditing.openUCDDialog()}" class="form-control #{tapSchemaEditing.selectedColumn.isChanged('ucd') ? 'changed' : ''}" id="column_ucd">
-                                                                #{tapSchemaEditing.selectedColumn.UCD}
+                                                                #{tapSchemaEditing.selectedColumn.getProperty('UCD').value}
                                                                 <f:ajax execute="@form" render=":ucd_search_form:search_UCD_modal_content" onevent="TSM.openSearchUCDModal"/>
                                                             </h:commandLink>
                                                         </div>
@@ -319,7 +319,7 @@
                                                             <h:inputText 
                                                                 id="column_unit"
                                                                 class="form-control #{tapSchemaEditing.selectedColumn.isChanged('unit') ? 'changed' : ''}"
-                                                                value="#{tapSchemaEditing.selectedColumn.unit}"
+                                                                value="#{tapSchemaEditing.selectedColumn.getProperty('unit').value}"
                                                                 autocomplete="off">
                                                                 <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                                                 <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'unit')}" onevent="TSM.textInputChanged" render="vounit-validator" />
@@ -363,7 +363,7 @@
                                                             <h:inputText 
                                                                 id="column_description"
                                                                 class="form-control #{tapSchemaEditing.selectedColumn.isChanged('description') ? 'changed' : ''}"
-                                                                value="#{tapSchemaEditing.selectedColumn.description}">
+                                                                value="#{tapSchemaEditing.selectedColumn.getProperty('description').value}">
                                                                 <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" />
                                                                 <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'description')}" onevent="TSM.textInputChanged" />
                                                             </h:inputText>
-- 
GitLab