/*
* Copyright (c) 2014, 2015 EBay Software Foundation and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.ovsdb.lib.schema;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.reflect.Invokable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.opendaylight.ovsdb.lib.error.ParsingException;
import org.opendaylight.ovsdb.lib.notation.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents an ovsdb database schema, which is comprised of a set of tables.
*/
public class DatabaseSchema {
private static final Logger LOG = LoggerFactory.getLogger(DatabaseSchema.class);
private String name;
private Version version;
private Map<String, TableSchema> tables;
public DatabaseSchema(Map<String, TableSchema> tables) {
this.tables = tables;
}
public DatabaseSchema(String name, Version version, Map<String, TableSchema> tables) {
this.name = name;
this.version = version;
this.tables = tables;
}
public Set<String> getTables() {
return this.tables.keySet();
}
public boolean hasTable(String table) {
return this.getTables().contains(table);
}
public <E extends TableSchema<E>> E table(String tableName, Class<E> clazz) {
TableSchema<E> table = tables.get(tableName);
if (clazz.isInstance(table)) {
return clazz.cast(table);
}
return createTableSchema(clazz, table);
}
protected <E extends TableSchema<E>> E createTableSchema(Class<E> clazz, TableSchema<E> table) {
Constructor<E> declaredConstructor;
try {
declaredConstructor = clazz.getDeclaredConstructor(TableSchema.class);
} catch (NoSuchMethodException e) {
String message = String.format("Class %s does not have public constructor that accepts TableSchema object",
clazz);
throw new IllegalArgumentException(message, e);
}
Invokable<E, E> invokable = Invokable.from(declaredConstructor);
try {
return invokable.invoke(null, table);
} catch (InvocationTargetException | IllegalAccessException e) {
String message = String.format("Not able to create instance of class %s using public constructor "
+ "that accepts TableSchema object", clazz);
throw new IllegalArgumentException(message, e);
}
}
//todo : this needs to move to a custom factory
public static DatabaseSchema fromJson(String dbName, JsonNode json) {
if (!json.isObject() || !json.has("tables")) {
throw new ParsingException("bad DatabaseSchema root, expected \"tables\" as child but was not found");
}
if (!json.isObject() || !json.has("version")) {
throw new ParsingException("bad DatabaseSchema root, expected \"version\" as child but was not found");
}
Version dbVersion = Version.fromString(json.get("version").asText());
Map<String, TableSchema> tables = new HashMap<>();
for (Iterator<Map.Entry<String, JsonNode>> iter = json.get("tables").fields(); iter.hasNext(); ) {
Map.Entry<String, JsonNode> table = iter.next();
LOG.trace("Read schema for table[{}]:{}", table.getKey(), table.getValue());
//todo : this needs to done by a factory
tables.put(table.getKey(), new GenericTableSchema().fromJson(table.getKey(), table.getValue()));
}
return new DatabaseSchema(dbName, dbVersion, tables);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Version getVersion() {
return version;
}
public void setVersion(Version version) {
this.version = version;
}
public void populateInternallyGeneratedColumns() {
for (TableSchema tableSchema : tables.values()) {
tableSchema.populateInternallyGeneratedColumns();
}
}
}