From: Robert Varga Date: Sat, 30 Nov 2019 08:26:00 +0000 (+0100) Subject: Make TableSchema/DatabaseSchema immutable X-Git-Tag: release/sodium-sr2~23 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=562d45084980bd9093c0021d10223fa9f137d667;p=ovsdb.git Make TableSchema/DatabaseSchema immutable Having schemas completely immutable is beneficial, as we can propagate invariants properly. This patch makes TableSchema and DatabaseSchema use immutable maps internally, making sure the final bit is achieved. Change-Id: Ie7c9fd4aa9cba7f0af88c8886400e8e5c804d6af Signed-off-by: Robert Varga (cherry picked from commit 085195eebbac3ef2c4d2dcff483ac542eaa9163a) --- diff --git a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbClientImpl.java b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbClientImpl.java index 72afec334..372a6ed56 100644 --- a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbClientImpl.java +++ b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbClientImpl.java @@ -348,12 +348,12 @@ public class OvsdbClientImpl implements OvsdbClient { } return Futures.transform(getSchemaFromDevice(Collections.singletonList(database)), result -> { - final DatabaseSchema dbSchema = result.get(database); + DatabaseSchema dbSchema = result.get(database); if (dbSchema == null) { return null; } - dbSchema.populateInternallyGeneratedColumns(); + dbSchema = dbSchema.withInternallyGeneratedColumns(); final DatabaseSchema raced = schemas.putIfAbsent(database, dbSchema); return raced != null ? raced : dbSchema; }, executorService); diff --git a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/DatabaseSchema.java b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/DatabaseSchema.java index ccf43d13a..a80d653d0 100644 --- a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/DatabaseSchema.java +++ b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/DatabaseSchema.java @@ -8,7 +8,11 @@ package org.opendaylight.ovsdb.lib.schema; +import static java.util.Objects.requireNonNull; + import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.common.reflect.Invokable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -29,20 +33,20 @@ public class DatabaseSchema { private final String name; private final Version version; - private final Map tables; + private final ImmutableMap tables; public DatabaseSchema(final String name, final Version version, final Map tables) { - this.name = name; - this.version = version; - this.tables = tables; + this.name = requireNonNull(name); + this.version = requireNonNull(version); + this.tables = ImmutableMap.copyOf(tables); } public Set getTables() { - return this.tables.keySet(); + return tables.keySet(); } public boolean hasTable(final String table) { - return this.getTables().contains(table); + return tables.containsKey(table); } public > E table(final String tableName, final Class clazz) { @@ -105,9 +109,17 @@ public class DatabaseSchema { return version; } - public void populateInternallyGeneratedColumns() { + public DatabaseSchema withInternallyGeneratedColumns() { + return haveInternallyGeneratedColumns() ? this : new DatabaseSchema(name, version, + Maps.transformValues(tables, TableSchema::withInternallyGeneratedColumns)); + } + + protected final boolean haveInternallyGeneratedColumns() { for (TableSchema tableSchema : tables.values()) { - tableSchema.populateInternallyGeneratedColumns(); + if (!tableSchema.haveInternallyGeneratedColumns()) { + return false; + } } + return true; } } diff --git a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/GenericTableSchema.java b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/GenericTableSchema.java index 47a0d9a12..576073f6b 100644 --- a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/GenericTableSchema.java +++ b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/GenericTableSchema.java @@ -44,4 +44,16 @@ public class GenericTableSchema extends TableSchema { return new GenericTableSchema(tableName, columns); } + + @Override + public GenericTableSchema withInternallyGeneratedColumns() { + if (haveInternallyGeneratedColumns()) { + return this; + } + + final Map columns = new HashMap<>(getColumnSchemas()); + columns.put(UUID_COLUMN_SCHMEMA.getName(), UUID_COLUMN_SCHMEMA); + columns.put(VERSION_COLUMN_SCHMEMA.getName(), VERSION_COLUMN_SCHMEMA); + return new GenericTableSchema(getName(), columns); + } } diff --git a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/TableSchema.java b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/TableSchema.java index 15efee380..e63ecef6b 100644 --- a/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/TableSchema.java +++ b/library/impl/src/main/java/org/opendaylight/ovsdb/lib/schema/TableSchema.java @@ -7,12 +7,14 @@ */ package org.opendaylight.ovsdb.lib.schema; +import static java.util.Objects.requireNonNull; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableMap; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -26,24 +28,23 @@ import org.opendaylight.ovsdb.lib.operations.Insert; public abstract class TableSchema> { private static final AtomicColumnType UUID_COLUMN_TYPE = new AtomicColumnType(UuidBaseType.SINGLETON); - private static final ColumnSchema UUID_COLUMN_SCHMEMA = new ColumnSchema("_uuid", UUID_COLUMN_TYPE); - private static final ColumnSchema VERSION_COLUMN_SCHMEMA = new ColumnSchema("_version", UUID_COLUMN_TYPE); + protected static final ColumnSchema UUID_COLUMN_SCHMEMA = new ColumnSchema("_uuid", UUID_COLUMN_TYPE); + protected static final ColumnSchema VERSION_COLUMN_SCHMEMA = new ColumnSchema("_version", UUID_COLUMN_TYPE); private final String name; - private final Map columns; + private final ImmutableMap columns; protected TableSchema(final String name) { - this.name = name; - this.columns = new HashMap<>(); + this(name, ImmutableMap.of()); } protected TableSchema(final String name, final Map columns) { - this.name = name; - this.columns = columns; + this.name = requireNonNull(name); + this.columns = ImmutableMap.copyOf(columns); } public Set getColumns() { - return this.columns.keySet(); + return columns.keySet(); } public Map getColumnSchemas() { @@ -51,11 +52,11 @@ public abstract class TableSchema> { } public boolean hasColumn(final String column) { - return this.getColumns().contains(column); + return columns.containsKey(column); } public ColumnType getColumnType(final String column) { - return this.columns.get(column).getType(); + return columns.get(column).getType(); } public > E as(final Class clazz) { @@ -100,7 +101,7 @@ public abstract class TableSchema> { } public ColumnSchema column(final String column) { - return this.columns.get(column); + return columns.get(column); } public String getName() { @@ -163,8 +164,9 @@ public abstract class TableSchema> { * a specific Schema implementation detail & hence adding it by default in the Library * for better application experience using the library. */ - public void populateInternallyGeneratedColumns() { - columns.put("_uuid", UUID_COLUMN_SCHMEMA); - columns.put("_version", VERSION_COLUMN_SCHMEMA); + public abstract E withInternallyGeneratedColumns(); + + protected final boolean haveInternallyGeneratedColumns() { + return hasColumn(UUID_COLUMN_SCHMEMA.getName()) && hasColumn(VERSION_COLUMN_SCHMEMA.getName()); } }