}
if (type.isObject()) {
//json like {"type" : "string", "enum": ["set", ["access", "native-tagged"]]}" for key or value
- final JsonNode nestedType = type.get("type");
- if (nestedType != null) {
- final BaseType ret = builderFor(nestedType.asText());
- if (ret != null) {
- ret.fillConstraints(type);
- return ret;
+ final JsonNode typeName = type.get("type");
+ if (typeName != null) {
+ final BaseTypeFactory<?> factory = factoryFor(typeName.asText());
+ if (factory != null) {
+ return factory.create(type);
}
}
}
return null;
}
- abstract void fillConstraints(JsonNode type);
-
public abstract Object toValue(JsonNode value);
public abstract void validate(Object value);
}
}
- // Create a new instance for customization
- private static BaseType builderFor(final String type) {
+ // Find a factory for custom instantiation
+ private static BaseTypeFactory<?> factoryFor(final String type) {
switch (type) {
case "boolean":
- return new BooleanBaseType();
+ return BooleanBaseType.FACTORY;
case "integer":
- return new IntegerBaseType();
+ return IntegerBaseType.FACTORY;
case "real":
- return new RealBaseType();
+ return RealBaseType.FACTORY;
case "string":
- return new StringBaseType();
+ return StringBaseType.FACTORY;
case "uuid":
- return new UuidBaseType();
+ return UuidBaseType.FACTORY;
default:
LOG.debug("Unknown base type {}", type);
return null;
}
}
-
}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class BaseTypeFactory<T extends BaseType<T>> {
+
+ abstract T create(JsonNode typeDefinition);
+
+ abstract static class WithEnum<T extends BaseType<T>, N extends Number> extends BaseTypeFactory<T> {
+
+ final ImmutableSet<N> parseEnums(final JsonNode node) {
+ final List<N> tmp = new ArrayList<>();
+ for (JsonNode enm : node.get(1)) {
+ tmp.add(getEnumValue(enm));
+ }
+ return ImmutableSet.copyOf(tmp);
+ }
+
+ abstract N getEnumValue(JsonNode jsonEnum);
+ }
+}
import com.fasterxml.jackson.databind.JsonNode;
-final class BooleanBaseType extends BaseType {
+final class BooleanBaseType extends BaseType<BooleanBaseType> {
static final BooleanBaseType SINGLETON = new BooleanBaseType();
-
- @Override
- void fillConstraints(final JsonNode node) {
- //no op
- }
+ static final BaseTypeFactory<BooleanBaseType> FACTORY = new BaseTypeFactory<>() {
+ @Override
+ BooleanBaseType create(final JsonNode typeDefinition) {
+ // No constraints possible, just return the singleton
+ return SINGLETON;
+ }
+ };
@Override
public Object toValue(final JsonNode value) {
package org.opendaylight.ovsdb.lib.schema;
import com.fasterxml.jackson.databind.JsonNode;
-import java.util.HashSet;
-import java.util.Optional;
+import com.google.common.collect.ImmutableSet;
import java.util.Set;
final class IntegerBaseType extends BaseType<IntegerBaseType> {
- static final IntegerBaseType SINGLETON = new IntegerBaseType();
+ static final IntegerBaseType SINGLETON = new IntegerBaseType(Long.MIN_VALUE, Long.MAX_VALUE, null);
+ static final BaseTypeFactory<IntegerBaseType> FACTORY = new Factory();
- private long min = Long.MIN_VALUE;
- private long max = Long.MAX_VALUE;
- private Set<Integer> enums;
+ private final long min;
+ private final long max;
+ private final ImmutableSet<Integer> enums;
- @Override
- void fillConstraints(final JsonNode type) {
- JsonNode typeMaxNode = type.get("maxInteger");
- if (typeMaxNode != null) {
- max = typeMaxNode.asLong();
- }
- JsonNode typeMinNode = type.get("minInteger");
- if (typeMinNode != null) {
- min = typeMinNode.asLong();
- }
- Optional<Set<Integer>> typeEnumsOpt = populateEnum(type);
- if (typeEnumsOpt.isPresent()) {
- enums = typeEnumsOpt.get();
- }
+ IntegerBaseType(final long min, final long max, final ImmutableSet<Integer> enums) {
+ this.min = min;
+ this.max = max;
+ this.enums = enums;
}
@Override
}
- private static Optional<Set<Integer>> populateEnum(final JsonNode node) {
- if (node.has("enum")) {
- Set<Integer> nodesEnums = new HashSet<>();
- JsonNode anEnum = node.get("enum").get(1);
- for (JsonNode enm : anEnum) {
- nodesEnums.add(enm.asInt());
- }
- return Optional.of(nodesEnums);
- } else {
- return Optional.empty();
- }
- }
-
public long getMin() {
return min;
}
}
return true;
}
-}
\ No newline at end of file
+
+ private static final class Factory extends BaseTypeFactory.WithEnum<IntegerBaseType, Integer> {
+ @Override
+ IntegerBaseType create(final JsonNode typeDefinition) {
+ final JsonNode typeMaxNode = typeDefinition.get("maxInteger");
+ final long max = typeMaxNode != null ? typeMaxNode.asLong() : Long.MAX_VALUE;
+
+ final JsonNode typeMinNode = typeDefinition.get("minInteger");
+ final long min = typeMinNode != null ? typeMinNode.asLong() : Long.MIN_VALUE;
+
+ final JsonNode typeEnumNode = typeDefinition.get("enum");
+ final ImmutableSet<Integer> enums = typeEnumNode != null ? parseEnums(typeEnumNode) : null;
+
+ return min == Long.MIN_VALUE && max == Long.MAX_VALUE && enums == null ? SINGLETON
+ : new IntegerBaseType(min, max, enums);
+ }
+
+ @Override
+ Integer getEnumValue(final JsonNode jsonEnum) {
+ return jsonEnum.asInt();
+ }
+ }
+}
package org.opendaylight.ovsdb.lib.schema;
import com.fasterxml.jackson.databind.JsonNode;
-import java.util.HashSet;
-import java.util.Optional;
+import com.google.common.collect.ImmutableSet;
import java.util.Set;
final class RealBaseType extends BaseType<RealBaseType> {
- static final RealBaseType SINGLETON = new RealBaseType();
+ static final RealBaseType SINGLETON = new RealBaseType(Double.MIN_VALUE, Double.MAX_VALUE, null);
+ static final BaseTypeFactory<RealBaseType> FACTORY = new Factory();
- private double min = Double.MIN_VALUE;
- private double max = Double.MAX_VALUE;
- private Set<Double> enums;
+ private final double min;
+ private final double max;
+ private final ImmutableSet<Double> enums;
- @Override
- void fillConstraints(final JsonNode type) {
- JsonNode typeMaxNode = type.get("maxReal");
- if (typeMaxNode != null) {
- max = typeMaxNode.asLong();
- }
- JsonNode typeMinNode = type.get("minReal");
- if (typeMinNode != null) {
- min = typeMinNode.asLong();
- }
- Optional<Set<Double>> typeEnumsOpt = populateEnum(type);
- if (typeEnumsOpt.isPresent()) {
- enums = typeEnumsOpt.get();
- }
+ RealBaseType(final double min, final double max, final ImmutableSet<Double> enums) {
+ this.min = min;
+ this.max = max;
+ this.enums = enums;
}
@Override
}
- private static Optional<Set<Double>> populateEnum(final JsonNode node) {
- if (node.has("enum")) {
- Set<Double> nodesEnums = new HashSet<>();
- JsonNode anEnum = node.get("enum").get(1);
- for (JsonNode enm : anEnum) {
- nodesEnums.add(enm.asDouble());
- }
- return Optional.of(nodesEnums);
- } else {
- return Optional.empty();
- }
- }
-
public double getMin() {
return min;
}
}
return true;
}
-}
\ No newline at end of file
+
+ private static final class Factory extends BaseTypeFactory.WithEnum<RealBaseType, Double> {
+ @Override
+ RealBaseType create(final JsonNode typeDefinition) {
+ // FIXME: is asLong() appropriate here?
+ final JsonNode typeMaxNode = typeDefinition.get("maxReal");
+ final double max = typeMaxNode != null ? typeMaxNode.asLong() : Double.MAX_VALUE;
+
+ final JsonNode typeMinNode = typeDefinition.get("minReal");
+ final double min = typeMinNode != null ? typeMinNode.asLong() : Double.MIN_VALUE;
+
+ final JsonNode typeEnumNode = typeDefinition.get("enum");
+ final ImmutableSet<Double> enums = typeEnumNode != null ? parseEnums(typeEnumNode) : null;
+
+ // TODO: improve accuracy here -- requires understanding the FIXME above
+ return typeMinNode == null && typeMaxNode == null && enums == null ? SINGLETON
+ : new RealBaseType(min, max, enums);
+ }
+
+ @Override
+ Double getEnumValue(final JsonNode jsonEnum) {
+ return jsonEnum.asDouble();
+ }
+ }
+}
package org.opendaylight.ovsdb.lib.schema;
import com.fasterxml.jackson.databind.JsonNode;
-import java.util.HashSet;
-import java.util.Optional;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
final class StringBaseType extends BaseType<StringBaseType> {
- static final StringBaseType SINGLETON = new StringBaseType();
+ // FIXME: negative minimum leng
+ static final StringBaseType SINGLETON = new StringBaseType(Integer.MIN_VALUE, Integer.MAX_VALUE, null);
+ static final BaseTypeFactory<StringBaseType> FACTORY = new Factory();
- private int minLength = Integer.MIN_VALUE;
- private int maxLength = Integer.MAX_VALUE;
- private Set<String> enums;
+ private final int minLength;
+ private final int maxLength;
+ private final ImmutableSet<String> enums;
- @Override
- void fillConstraints(final JsonNode type) {
- JsonNode typeMaxNode = type.get("maxLength");
- if (typeMaxNode != null) {
- maxLength = typeMaxNode.asInt();
- }
- JsonNode typeMinNode = type.get("minLength");
- if (typeMinNode != null) {
- minLength = typeMinNode.asInt();
- }
- Optional<Set<String>> typeEnumsOpt = populateEnum(type);
- if (typeEnumsOpt.isPresent()) {
- enums = typeEnumsOpt.get();
- }
+ StringBaseType(final int min, final int max, final ImmutableSet<String> enums) {
+ this.minLength = min;
+ this.maxLength = max;
+ this.enums = enums;
}
@Override
}
- private static Optional<Set<String>> populateEnum(final JsonNode node) {
- if (node.has("enum")) {
- Set<String> nodesEnums = new HashSet<>();
- JsonNode enumVal = node.get("enum");
- if (enumVal.isArray()) {
- JsonNode anEnum = enumVal.get(1);
- for (JsonNode enm : anEnum) {
- nodesEnums.add(enm.asText());
- }
- } else if (enumVal.isTextual()) {
- nodesEnums.add(enumVal.asText());
- }
- return Optional.of(nodesEnums);
- } else {
- return Optional.empty();
- }
- }
-
public int getMinLength() {
return minLength;
}
}
return true;
}
+
+ private static final class Factory extends BaseTypeFactory<StringBaseType> {
+ @Override
+ StringBaseType create(final JsonNode typeDefinition) {
+ final JsonNode typeMaxNode = typeDefinition.get("maxLength");
+ final int max = typeMaxNode != null ? typeMaxNode.asInt() : Integer.MAX_VALUE;
+
+ final JsonNode typeMinNode = typeDefinition.get("minLength");
+ final int min = typeMinNode != null ? typeMinNode.asInt() : Integer.MIN_VALUE;
+
+ final JsonNode typeEnumNode = typeDefinition.get("enum");
+ final ImmutableSet<String> enums = typeEnumNode != null ? parseEnums(typeEnumNode) : null;
+
+ return min == Integer.MIN_VALUE && max == Integer.MAX_VALUE && enums == null ? SINGLETON
+ : new StringBaseType(min, max, enums);
+ }
+
+
+ private static ImmutableSet<String> parseEnums(final JsonNode enumVal) {
+ if (enumVal.isTextual()) {
+ return ImmutableSet.of(enumVal.asText());
+ }
+ if (enumVal.isArray()) {
+ final List<String> tmp = new ArrayList<>();
+ JsonNode anEnum = enumVal.get(1);
+ for (JsonNode enm : anEnum) {
+ tmp.add(enm.asText());
+ }
+ return ImmutableSet.copyOf(tmp);
+ }
+ return ImmutableSet.of();
+ }
+ }
}
// These enum types correspond to JSON values and need to be in lower-case currently
public enum RefType { strong, weak }
- static final UuidBaseType SINGLETON = new UuidBaseType();
+ static final UuidBaseType SINGLETON = new UuidBaseType(null, null);
+ static final BaseTypeFactory<UuidBaseType> FACTORY = new BaseTypeFactory<>() {
+ @Override
+ UuidBaseType create(final JsonNode typeDefinition) {
+ final JsonNode refTableNode = typeDefinition.get("refTable");
+ final String refTable = refTableNode != null ? refTableNode.asText() : null;
- private String refTable;
- private UuidBaseType.RefType refType;
+ final JsonNode refTypeJson = typeDefinition.get("refType");
+ final RefType refType = refTypeJson != null ? RefType.valueOf(refTypeJson.asText()) : RefType.strong;
- @Override
- void fillConstraints(final JsonNode node) {
- JsonNode refTableNode = node.get("refTable");
- refTable = refTableNode != null ? refTableNode.asText() : null;
+ // FIXME: this is weird from refTable/refType perspective -- if there is no table, we should not default
+ // to strong reference and squash to singleton
+ return new UuidBaseType(refTable, refType);
+ }
+ };
+
+ private final String refTable;
+ private final RefType refType;
- JsonNode refTypeJson = node.get("refType");
- refType = refTypeJson != null ? RefType.valueOf(refTypeJson.asText()) : RefType.strong;
+ UuidBaseType(final String refTable, final RefType refType) {
+ this.refTable = refTable;
+ this.refType = refType;
}
@Override