<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
+ <dependency>
+ <artifactId>junit</artifactId>
+ <groupId>junit</groupId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class Extensible {
+
+ @JsonIgnore
+ private Map<String, Object> extra = new LinkedHashMap<String, Object>();
+
+ @JsonAnyGetter
+ public Map<String, Object> any() {
+ return extra;
+ }
+
+ @JsonAnySetter
+ public void set(String name, Object value) {
+ extra.put(name, value);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.regex.Pattern;
+
+public class FormatValidator {
+
+ /**
+ * RFC 7285 section 10.1
+ * */
+ private static final String VALID_CHARSET = "a-zA-Z_0-9\\-:@";
+ private static final Pattern VALID_ID_PATTERN
+ = Pattern.compile("^["+VALID_CHARSET+"]{1,64}$");
+ private static final String VALID_CHARSET_WITH_DOT = VALID_CHARSET + "\\.";
+ private static final Pattern VALID_ID_PATTERN_WITH_DOT
+ = Pattern.compile("^["+VALID_CHARSET_WITH_DOT+"]{1,64}$");
+ private static final String VALID_TAG_CHARSET = "!-~";
+ private static final Pattern VALID_TAG_PATTERN
+ = Pattern.compile("^["+VALID_TAG_CHARSET+"]{1,64}$");
+ private static final String VALID_ADDR_IPV4 = "^ipv4:(([0-9]|[1-9][0-9]|1[0-9][0-9]|"
+ + "2[0-4][0-9]|25[0-5])\\.){3}"
+ + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
+ + "(%[\\p{N}\\p{L}]+)?$";
+ private static final Pattern VALID_ADDR_IPV4_PATTERN
+ = Pattern.compile(VALID_ADDR_IPV4);
+ private static final String VALID_ADDR_IPV6_1 = "^ipv6:((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}"
+ + "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|"
+ + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}"
+ + "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))"
+ + "(%[\\p{N}\\p{L}]+)?$";
+ private static final Pattern VALID_ADDR_IPV6_1_PATTERN
+ = Pattern.compile(VALID_ADDR_IPV6_1);
+ private static final String VALID_ADDR_IPV6_2 = "^ipv6:((([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|"
+ + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)"
+ + "(%.+)?)$";
+ private static final Pattern VALID_ADDR_IPV6_2_PATTERN
+ = Pattern.compile(VALID_ADDR_IPV6_2);
+ private static final String VALID_OPERATORS = "(gt|lt|ge|le|eq)";
+ private static final Pattern VALID_CONSTRAINTS_PATTERN
+ = Pattern.compile("^"+VALID_OPERATORS+" [0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
+
+
+ public static boolean validId(String id) {
+ return VALID_ID_PATTERN.matcher(id).matches();
+ }
+
+ public static boolean validIdWithDots(String id) {
+ return VALID_ID_PATTERN_WITH_DOT.matcher(id).matches();
+ }
+
+ /**
+ * RFC 7285 section 10.1
+ * */
+ public static boolean validPid(String id) {
+ return validId(id);
+ }
+
+ public static boolean validPidWithDots(String id) {
+ return validIdWithDots(id);
+ }
+
+ /**
+ * RFC 7285 section 10.2
+ * */
+ public static boolean validResourceId(String id) {
+ return validId(id);
+ }
+
+ public static boolean validResourceIdWithDots(String id) {
+ return validIdWithDots(id);
+ }
+
+ /**
+ * RFC 7285 section 10.3
+ * */
+ public static boolean validTag(String tag) {
+ return VALID_TAG_PATTERN.matcher(tag).matches();
+ }
+ /**
+ * RFC 7285 section 10.8.1
+ * */
+ public static boolean validSpecificEndpointProperty(String prop) {
+ /* TODO maybe enhance the performance? */
+ return validId(prop) && (prop.indexOf('@') == -1);
+ }
+
+ public static boolean validSpecificEndpointPropertyWithDots(String prop) {
+ /* TODO maybe enhance the performance? */
+ return validIdWithDots(prop) && (prop.indexOf('@') == -1);
+ }
+
+ /**
+ * RFC 7285 seciton 10.8.2
+ * */
+ public static boolean validGlobalEndpointProperty(String prop) {
+ return (prop.length() <= 32) && validId(prop);
+ }
+
+ /**
+ * RFC 7285 section 11.3.2
+ * */
+ public static boolean validFilterConstraint(String constrant) {
+ return VALID_CONSTRAINTS_PATTERN.matcher(constrant).matches();
+ }
+
+ public static boolean validAddressIpv4(String address) {
+ return VALID_ADDR_IPV4_PATTERN.matcher(address).matches();
+ }
+
+ public static boolean validAddressIpv6(String address) {
+ return VALID_ADDR_IPV6_1_PATTERN.matcher(address).matches() &&
+ VALID_ADDR_IPV6_2_PATTERN.matcher(address).matches();
+ }
+
+ public static boolean validEndpointAddress(String address) {
+ return validAddressIpv4(address) || validAddressIpv6(address);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+public class MediaType {
+
+ /** The media types defined in [RFC7285]
+ *
+ * The media types defined here should be identical to those
+ * generated by alto-model, the main reason we need this is
+ * the ones defined here are *STRING LITERALS*.
+ * */
+
+ public static final String ALTO_DIRECTORY
+ = "application/alto-directory+json";
+ public static final String ALTO_NETWORKMAP
+ = "application/alto-networkmap+json";
+ public static final String ALTO_NETWORKMAP_FILTER
+ = "application/alto-networkmapfilter+json";
+ public static final String ALTO_COSTMAP
+ = "application/alto-costmap+json";
+ public static final String ALTO_COSTMAP_FILTER
+ = "application/alto-costmapfilter+json";
+ public static final String ALTO_ENDPOINT_PROP
+ = "application/alto-endpointprop+json";
+ public static final String ALTO_ENDPOINT_PROPPARAMS
+ = "application/alto-endpointpropparams+json";
+ public static final String ALTO_ENDPOINT_COST
+ = "application/alto-endpointcost+json";
+ public static final String ALTO_ENDPOINT_COSTPARAMS
+ = "application/alto-endpointcostparams+json";
+ public static final String ALTO_ERROR
+ = "application/alto-error+json";
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedList;
+import java.util.LinkedHashMap;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Cost Map: defined in RFC7285 secion 11.2.3
+ * */
+public class RFC7285CostMap {
+
+ public static class Meta extends Extensible {
+
+ @JsonProperty("dependent-vtags")
+ public List<RFC7285VersionTag> netmap_tags = new LinkedList<RFC7285VersionTag>();
+
+ @JsonProperty("cost-type")
+ public RFC7285CostType costType;
+ }
+
+ /**
+ * for filtered-cost-map service, RFC7285 secion 11.3.2
+ * */
+ public static class Filter {
+
+ @JsonProperty("cost-type")
+ public RFC7285CostType costType;
+
+ @JsonProperty("pids")
+ public RFC7285QueryPairs pids;
+
+ @JsonProperty("constraints")
+ public List<String> constraints;
+ }
+
+ @JsonProperty("meta")
+ public Meta meta = new Meta();
+
+ @JsonProperty("cost-map")
+ public Map<String, Map<String, Object>> map
+ = new LinkedHashMap<String, Map<String, Object>>();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Arrays;
+
+public class RFC7285CostType {
+
+ @JsonProperty("cost-mode")
+ public String mode = null;
+
+ @JsonProperty("cost-metric")
+ public String metric = null;
+
+ @JsonProperty("description")
+ public String description = null;
+
+ public RFC7285CostType() {
+ }
+
+ public RFC7285CostType(String mode, String metric) {
+ this.mode = mode;
+ this.metric = metric;
+ }
+
+ public RFC7285CostType(String mode, String metric, String description) {
+ this.mode = mode;
+ this.metric = metric;
+ this.description = description;
+ }
+
+ @Override
+ public int hashCode() {
+ String[] members = { metric, mode };
+ return Arrays.hashCode(members);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj != null ? (obj instanceof RFC7285CostType) : false))
+ return false;
+
+ RFC7285CostType other = (RFC7285CostType)obj;
+ String[] lhs = { metric, mode };
+ String[] rhs = { other.metric, other.mode };
+ return Arrays.equals(lhs, rhs);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+
+public class RFC7285Endpoint {
+
+ public static class AddressGroup extends Extensible {
+
+ @JsonIgnore
+ public static final String IPV4_LABEL = "ipv4";
+
+ @JsonIgnore
+ public static final String IPV6_LABEL = "ipv6";
+
+ @JsonProperty(IPV4_LABEL)
+ public List<String> ipv4 = new ArrayList<String>();
+
+ @JsonProperty(IPV6_LABEL)
+ public List<String> ipv6 = new ArrayList<String>();
+
+ }
+
+ public static class PropertyRequest {
+
+ @JsonProperty(value="properties")
+ public List<String> properties;
+
+ @JsonProperty(value="endpoints")
+ public List<String> endpoints;
+ }
+
+ public static class PropertyResponse {
+
+ public static class Meta extends Extensible {
+
+ @JsonProperty("dependent-vtags")
+ public List<RFC7285VersionTag> netmap_tags = new ArrayList<RFC7285VersionTag>();
+
+ }
+
+ @JsonProperty("meta")
+ public Meta meta = new Meta();
+
+ @JsonProperty("endpoint-properties")
+ public Map<String, Map<String, Object>> answer
+ = new LinkedHashMap<String, Map<String, Object>>();
+ }
+
+ public static class CostRequest {
+
+ @JsonProperty("cost-type")
+ public RFC7285CostType costType;
+
+ @JsonProperty("constraints")
+ public List<String> constraints = new ArrayList<String>();
+
+ @JsonProperty("endpoints")
+ public RFC7285QueryPairs endpoints;
+ }
+
+ public static class CostResponse {
+
+ public static class Meta extends Extensible {
+
+ @JsonProperty("cost-type")
+ public RFC7285CostType costType = new RFC7285CostType();
+
+ }
+
+ @JsonProperty("meta")
+ public Meta meta = new Meta();
+
+ @JsonProperty("endpoint-cost-map")
+ public Map<String, Map<String, Object>> answer = null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class RFC7285EndpointPropertyMap {
+
+ public static class Meta extends Extensible {
+ @JsonProperty("dependent-vtags")
+ public List<RFC7285VersionTag> netmap_tags;
+ }
+
+ @JsonProperty("meta")
+ public Meta meta;
+
+ @JsonProperty("endpoint-properties")
+ public Map<String, Map<String, String>> map
+ = new LinkedHashMap<String, Map<String, String>>();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class RFC7285IRD {
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public class Meta {
+ @JsonProperty("default-alto-network-map")
+ public String defaultAltoNetworkMap;
+
+ @JsonProperty("cost-types")
+ public Map<String, RFC7285CostType> costTypes = new LinkedHashMap<String, RFC7285CostType>();
+
+ }
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public class Capability {
+ @JsonProperty("cost-constraints")
+ public Boolean costConstraints;
+
+ @JsonProperty("cost-type-names")
+ public List<String> costTypeNames;
+
+ @JsonProperty("prop-types")
+ public List<String> propTypes;
+ }
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ public class Entry {
+ @JsonProperty("uri")
+ public String uri;
+
+ @JsonProperty("media-type")
+ public String mediaType;
+
+ @JsonProperty("accepts")
+ public String accepts;
+
+ @JsonProperty("capabilities")
+ public Capability capabilities;
+
+ @JsonProperty("uses")
+ public List<String> uses;
+ }
+
+ @JsonProperty("meta")
+ public Meta meta = new Meta();
+
+ @JsonProperty("resources")
+ public Map<String, Entry> resources = new LinkedHashMap<String, Entry>();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+public class RFC7285JSONMapper {
+
+ private ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(Include.NON_DEFAULT)
+ .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
+
+ public RFC7285Endpoint.AddressGroup asAddressGroup(String json) throws Exception {
+ return mapper.readValue(json, RFC7285Endpoint.AddressGroup.class);
+ }
+
+ public RFC7285Endpoint.PropertyRequest asPropertyRequest(String json) throws Exception {
+ RFC7285Endpoint.PropertyRequest ret = mapper.readValue(json, RFC7285Endpoint.PropertyRequest.class);
+
+ if (ret.properties == null) {
+ throw new JsonMappingException("Missing field:properties");
+ }
+ if (ret.endpoints == null) {
+ throw new JsonMappingException("Missing field:endpoints");
+ }
+ return ret;
+ }
+
+ public RFC7285Endpoint.PropertyResponse asPropertyResponse(String json) throws Exception {
+ return mapper.readValue(json, RFC7285Endpoint.PropertyResponse.class);
+ }
+
+ public RFC7285Endpoint.CostRequest asCostRequest(String json) throws Exception {
+ RFC7285Endpoint.CostRequest ret = mapper.readValue(json, RFC7285Endpoint.CostRequest.class);
+ if (ret.costType == null) {
+ throw new JsonMappingException("Missing field:cost-type");
+ }
+ if (ret.endpoints == null) {
+ throw new JsonMappingException("Missing field:endpoints");
+ }
+ return ret;
+ }
+
+ public RFC7285Endpoint.CostResponse asCostResponse(String json) throws Exception {
+ return mapper.readValue(json, RFC7285Endpoint.CostResponse.class);
+ }
+
+ public RFC7285CostMap asCostMap(String json) throws Exception {
+ return mapper.readValue(json, RFC7285CostMap.class);
+ }
+
+ public List<RFC7285CostMap> asCostMapList(String json) throws Exception {
+ return Arrays.asList(mapper.readValue(json, RFC7285CostMap[].class));
+ }
+
+ public RFC7285CostType asCostType(String json) throws Exception {
+ return mapper.readValue(json, RFC7285CostType.class);
+ }
+
+ public RFC7285Endpoint asEndpoint(String json) throws Exception {
+ return mapper.readValue(json, RFC7285Endpoint.class);
+ }
+
+ public Extensible asExtensible(String json) throws Exception {
+ return mapper.readValue(json, Extensible.class);
+ }
+
+ public RFC7285IRD asIRD(String json) throws Exception {
+ return mapper.readValue(json, RFC7285IRD.class);
+ }
+
+ public RFC7285NetworkMap asNetworkMap(String json) throws Exception {
+ return mapper.readValue(json, RFC7285NetworkMap.class);
+ }
+
+ public List<RFC7285NetworkMap> asNetworkMapList(String json) throws Exception {
+ return Arrays.asList(mapper.readValue(json, RFC7285NetworkMap[].class));
+ }
+
+ public RFC7285NetworkMap.Filter asNetworkMapFilter(String json) throws Exception {
+ RFC7285NetworkMap.Filter ret = mapper.readValue(json, RFC7285NetworkMap.Filter.class);
+ if (ret.pids == null) {
+ throw new JsonMappingException("Missing field:pids");
+ }
+ return ret;
+ }
+
+ public RFC7285CostMap.Filter asCostMapFilter(String json) throws Exception {
+ RFC7285CostMap.Filter ret = mapper.readValue(json, RFC7285CostMap.Filter.class);
+ if (ret.costType == null) {
+ throw new JsonMappingException("Missing field:cost-type");
+ }
+ if (ret.pids == null) {
+ throw new JsonMappingException("Missing field:pids");
+ }
+ return ret;
+ }
+
+ public RFC7285VersionTag asVersionTag(String json) throws Exception {
+ return mapper.readValue(json, RFC7285VersionTag.class);
+ }
+
+ public RFC7285EndpointPropertyMap asEndpointPropMap(String json) throws Exception {
+ return mapper.readValue(json, RFC7285EndpointPropertyMap.class);
+ }
+
+ public String asJSON(Object obj) throws Exception {
+ return mapper.writeValueAsString(obj);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Network Map: defined in RFC 7285 section 11.2.1
+ * */
+public class RFC7285NetworkMap {
+
+ public static class Meta extends Extensible {
+
+ @JsonProperty("vtag")
+ public RFC7285VersionTag vtag = new RFC7285VersionTag();
+
+ }
+
+ /**
+ * used for filtered-network-map, RFC7285 secion 11.3.1
+ * */
+ public static class Filter {
+
+ @JsonProperty("pids")
+ public List<String> pids;
+ @JsonProperty("address-types")
+ public List<String> addressTypes;
+ }
+
+ @JsonProperty("meta")
+ public Meta meta = new Meta();
+
+ @JsonProperty("network-map")
+ public Map<String, RFC7285Endpoint.AddressGroup> map
+ = new LinkedHashMap<String, RFC7285Endpoint.AddressGroup>();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.List;
+import java.util.LinkedList;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class RFC7285QueryPairs {
+
+ @JsonProperty("srcs")
+ public List<String> src = new LinkedList<String>();
+
+ @JsonProperty("dsts")
+ public List<String> dst = new LinkedList<String>();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class RFC7285VersionTag {
+
+ @JsonProperty("resource-id")
+ public String rid;
+
+ @JsonProperty("tag")
+ public String tag;
+
+ public RFC7285VersionTag() {
+ rid = "";
+ tag = "";
+ }
+
+ public RFC7285VersionTag(String rid, String tag) {
+ this.rid = (rid != null ? rid : "");
+ this.tag = (tag != null ? tag : "");
+ }
+
+ public boolean incomplete() {
+ return (rid == null) || (tag == null) || (rid == "") || (tag == "");
+ }
+
+ private static char ILLEGAL = '$';
+
+ @Override
+ public int hashCode() {
+ return (rid + ILLEGAL + tag).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+
+ RFC7285VersionTag other = (RFC7285VersionTag)obj;
+ boolean _rid = (rid == null ? (other.rid == null) : rid.equals(other.rid));
+ boolean _tag = (tag == null ? (other.tag == null) : tag.equals(other.tag));
+ return (_rid && _tag);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Yale University 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.alto.core.northbound.api.utils.rfc7285;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.ArrayList;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestRFC7285Types {
+
+ public RFC7285NetworkMap makeNetworkMap() {
+ /*
+ *
+ * {
+ * "meta" : {
+ * "vtag": {
+ * "resource-id": "my-default-network-map",
+ * "tag": "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785"
+ * }
+ * },
+ * "network-map": {
+ * "PID1" : {
+ * "ipv4" : [
+ * "192.0.2.0/24",
+ * "198.51.100.0/25"
+ * ]
+ * },
+ * "PID2" : {
+ * "ipv4" : [
+ * "198.51.100.128/25"
+ * ]
+ * },
+ * "PID3" : {
+ * "ipv4" : [
+ * "0.0.0.0/0"
+ * ],
+ * "ipv6" : [
+ * "::/0"
+ * ]
+ * }
+ * }
+ * }
+ *
+ * */
+ RFC7285NetworkMap nm = new RFC7285NetworkMap();
+ nm.meta.vtag = new RFC7285VersionTag("my-default-network-map",
+ "da65eca2eb7a10ce8b059740b0b2e3f8eb1d4785");
+
+ nm.map.put("PID1", new RFC7285Endpoint.AddressGroup());
+ nm.map.get("PID1").ipv4.add("192.0.2.0/24");
+ nm.map.get("PID1").ipv4.add("198.51.100.0/25");
+
+ nm.map.put("PID2", new RFC7285Endpoint.AddressGroup());
+ nm.map.get("PID2").ipv4.add("198.51.100.128/25");
+
+ nm.map.put("PID3", new RFC7285Endpoint.AddressGroup());
+ nm.map.get("PID3").ipv4.add("0.0.0.0/0");
+ nm.map.get("PID3").ipv6.add("::/0");
+
+ return nm;
+ }
+
+ @Test
+ public void test() {
+ }
+
+ public <T> void assertCollectionEquals(Collection<T> lhs, Collection<T> rhs) {
+ Set<T> _lhs = new HashSet<T>(lhs);
+ Set<T> _rhs = new HashSet<T>(rhs);
+ assertEquals(lhs.size(), rhs.size());
+
+ for (T obj: lhs) {
+ assertTrue(_rhs.contains(obj));
+ }
+ }
+
+ @Test
+ public void testNetworkMap() throws Exception {
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285NetworkMap nm = makeNetworkMap();
+ String nmText = mapper.asJSON(nm);
+ RFC7285NetworkMap _nm = mapper.asNetworkMap(nmText);
+
+ assertEquals(nm.meta.vtag, _nm.meta.vtag);
+ assertEquals(nm.map.size(), _nm.map.size());
+ assertCollectionEquals(nm.map.get("PID1").ipv4, _nm.map.get("PID1").ipv4);
+ assertCollectionEquals(nm.map.get("PID2").ipv4, _nm.map.get("PID2").ipv4);
+ assertCollectionEquals(nm.map.get("PID3").ipv4, _nm.map.get("PID3").ipv4);
+ assertCollectionEquals(nm.map.get("PID3").ipv6, _nm.map.get("PID3").ipv6);
+
+ String addrGroupString = mapper.asJSON(nm.map.get("PID3"));
+ RFC7285Endpoint.AddressGroup _ag = mapper.asAddressGroup(addrGroupString);
+ assertCollectionEquals(nm.map.get("PID3").ipv4, _ag.ipv4);
+ assertCollectionEquals(nm.map.get("PID3").ipv6, _ag.ipv6);
+ }
+
+ @Test
+ public void testNetworkMapFilter() throws Exception {
+ /*
+ *
+ * {
+ * "pids": [ "PID1", "PID2" ]
+ * }
+ * */
+
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285NetworkMap.Filter filter = new RFC7285NetworkMap.Filter();
+ filter.pids = new ArrayList<String>();
+ filter.pids.add("PID1");
+ filter.pids.add("PID2");
+
+ String nmfString = mapper.asJSON(filter);
+ RFC7285NetworkMap.Filter _filter = mapper.asNetworkMapFilter(nmfString);
+ assertCollectionEquals(filter.pids, _filter.pids);
+ }
+
+ public RFC7285CostMap makeCostMap() {
+ /*
+ * {
+ * "meta": {
+ * "dependent-vtags" : [
+ * {
+ * "resource-id": "my-default-network-map",
+ * "tag": "3ee2cb7e8d63d9fab71b9b34cbf764436315542e"
+ * }
+ * ],
+ * "cost-type" : {
+ * "cost-mode": "numerical",
+ * "cost-metric": "routingcost"
+ * }
+ * },
+ * "cost-map" : {
+ * "PID1": { "PID1": 1, "PID2": 5, "PID3": 10 },
+ * "PID2": { "PID1": 5, "PID2": 1, "PID3": 15 },
+ * "PID3": { "PID1": 20, "PID2": 15 }
+ * }
+ * }
+ * */
+
+ RFC7285CostMap cm = new RFC7285CostMap();
+ cm.meta.costType = new RFC7285CostType("numerical", "routingcost");
+ cm.meta.netmap_tags.add(new RFC7285VersionTag("my-default-network-map",
+ "3ee2cb7e8d63d9fab71b9b34cbf764436315542e"));
+ cm.map.put("PID1", new LinkedHashMap<String, Object>());
+ cm.map.get("PID1").put("PID1", new Integer(1));
+ cm.map.get("PID1").put("PID2", new Integer(5));
+ cm.map.get("PID1").put("PID3", new Integer(10));
+ cm.map.put("PID2", new LinkedHashMap<String, Object>());
+ cm.map.get("PID2").put("PID1", new Integer(5));
+ cm.map.get("PID2").put("PID2", new Integer(1));
+ cm.map.get("PID2").put("PID3", new Integer(15));
+ cm.map.put("PID3", new LinkedHashMap<String, Object>());
+ cm.map.get("PID3").put("PID1", new Integer(20));
+ cm.map.get("PID3").put("PID2", new Integer(15));
+
+ return cm;
+ }
+
+ @Test
+ public void testCostMap() throws Exception {
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285CostMap cm = makeCostMap();
+
+ String cmString = mapper.asJSON(cm);
+ RFC7285CostMap _cm = mapper.asCostMap(cmString);
+
+ assertCollectionEquals(cm.meta.netmap_tags, _cm.meta.netmap_tags);
+ assertEquals(cm.meta.costType, _cm.meta.costType);
+
+ String pids[] = { "PID1", "PID2", "PID3" };
+ for (String pid: pids) {
+ assertCollectionEquals(cm.map.get(pid).entrySet(), _cm.map.get(pid).entrySet());
+ }
+ }
+
+ @Test
+ public void testCostMapFilter() throws Exception {
+ /*
+ * {
+ * "cost-type" : {
+ * "cost-mode": "numerical",
+ * "cost-metric": "routingcost"
+ * },
+ * "pids" : {
+ * "srcs" : [ "PID1" ],
+ * "dsts" : [ "PID1", "PID2", "PID3" ]
+ * }
+ * }
+ * */
+
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285CostMap.Filter filter = new RFC7285CostMap.Filter();
+ filter.costType = new RFC7285CostType("numerical", "routingcost", "test");
+ filter.pids = new RFC7285QueryPairs();
+ filter.pids.src.add("PID1");
+ filter.pids.dst.add("PID1");
+ filter.pids.dst.add("PID2");
+ filter.pids.dst.add("PID3");
+
+ String cmfString = mapper.asJSON(filter);
+ RFC7285CostMap.Filter _filter = mapper.asCostMapFilter(cmfString);
+
+ assertEquals(filter.costType, _filter.costType);
+ assertCollectionEquals(filter.pids.src, _filter.pids.src);
+ assertCollectionEquals(filter.pids.dst, _filter.pids.dst);
+ }
+
+ @Test
+ public void testECSRequest() throws Exception {
+ /*
+ * {
+ * "cost-type" : {
+ * "cost-mode": "ordinal",
+ * "cost-metric": "routingcost"
+ * },
+ * "endpoints": {
+ * "srcs": [ "ipv4:192.0.2.2" ],
+ * "dsts": [
+ * "ipv4:192.0.2.89",
+ * "ipv4:198.51.100.34",
+ * "ipv4:203.0.113.45"
+ * ]
+ * }
+ * }
+ * */
+
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285Endpoint.CostRequest req = new RFC7285Endpoint.CostRequest();
+ req.costType = new RFC7285CostType("ordinal", "routingcost", "test");
+ req.endpoints = new RFC7285QueryPairs();
+ req.endpoints.src.add("ipv4:192.0.2.2");
+ req.endpoints.dst.add("ipv4:192.0.2.89");
+ req.endpoints.dst.add("ipv4:198.51.100.34");
+ req.endpoints.dst.add("ipv4:203.0.113.45");
+
+ String ecsrString = mapper.asJSON(req);
+ RFC7285Endpoint.CostRequest _req = mapper.asCostRequest(ecsrString);
+
+ assertEquals(req.costType, _req.costType);
+ assertCollectionEquals(req.endpoints.src, _req.endpoints.src);
+ assertCollectionEquals(req.endpoints.dst, _req.endpoints.dst);
+ }
+
+ public RFC7285Endpoint.CostResponse makeECSResponse() {
+ /*
+ * {
+ * "meta": {
+ * "cost-type" : {
+ * "cost-mode": "ordinal",
+ * "cost-metric": "routingcost"
+ * }
+ * },
+ * "endpoint-cost-map" : {
+ * "ipv4:192.0.2.2": {
+ * "ipv4:192.0.2.89": 1,
+ * "ipv4:198.51.100.34": 2,
+ * "ipv4:203.0.113.45": 3
+ * },
+ * }
+ * }
+ * */
+
+ String src[] = { "ipv4:192.0.2.2" };
+ String dst[] = { "ipv4:192.0.2.89", "ipv4:198.51.100.34", "ipv4:203.0.113.45" };
+
+ RFC7285Endpoint.CostResponse ecsr = new RFC7285Endpoint.CostResponse();
+ ecsr.meta.costType = new RFC7285CostType("ordinal", "routingcost");
+ ecsr.answer = new LinkedHashMap<String, Map<String, Object>>();
+ ecsr.answer.put(src[0], new LinkedHashMap<String, Object>());
+ ecsr.answer.get(src[0]).put(dst[0], new Integer(1));
+ ecsr.answer.get(src[0]).put(dst[1], new Integer(2));
+ ecsr.answer.get(src[0]).put(dst[2], new Integer(3));
+
+ return ecsr;
+ }
+
+ @Test
+ public void testECSAnswer() throws Exception {
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285Endpoint.CostResponse ecsr = makeECSResponse();
+
+ String ecsrString = mapper.asJSON(ecsr);
+ RFC7285Endpoint.CostResponse _ecsr = mapper.asCostResponse(ecsrString);
+
+ assertEquals(ecsr.meta.costType, _ecsr.meta.costType);
+
+ String endpoints[] = { "ipv4:192.0.2.2" };
+ for (String endpoint: endpoints) {
+ assertCollectionEquals(ecsr.answer.get(endpoint).entrySet(),
+ _ecsr.answer.get(endpoint).entrySet());
+ }
+ }
+
+ @Test
+ public void testEPSRequest() throws Exception {
+ /*
+ * {
+ * "properties" : [
+ * "my-default-networkmap.pid",
+ * "priv:ietf-example-prop"
+ * ],
+ * "endpoints" : [
+ * "ipv4:192.0.2.34",
+ * "ipv4:203.0.113.129"
+ * ]
+ * }
+ */
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285Endpoint.PropertyRequest req = new RFC7285Endpoint.PropertyRequest();
+ if (req.properties == null)
+ req.properties = new ArrayList<String>();
+ req.properties.add("my-default-networkmap.pid");
+ req.properties.add("priv:ietf-example-prop");
+
+ if (req.endpoints == null)
+ req.endpoints = new ArrayList<String>();
+
+ req.endpoints.add("ipv4:192.0.2.34");
+ req.endpoints.add("ipv4:203.0.113.129");
+
+ String epsrString = mapper.asJSON(req);
+ RFC7285Endpoint.PropertyRequest _req = mapper.asPropertyRequest(epsrString);
+
+ assertCollectionEquals(req.properties, _req.properties);
+ assertCollectionEquals(req.endpoints, _req.endpoints);
+ }
+
+ @Test
+ public void testEPSResponse() throws Exception {
+ /*
+ * {
+ * "meta" : {
+ * "dependent-vtags" : [
+ * {
+ * "resource-id": "my-default-network-map",
+ * "tag": "7915dc0290c2705481c491a2b4ffbec482b3cf62"
+ * }
+ * ]
+ * },
+ * "endpoint-properties": {
+ * "ipv4:192.0.2.34": {
+ * "my-default-network-map.pid": "PID1",
+ * "priv:ietf-example-prop": "1"
+ * },
+ * "ipv4:203.0.113.129": {
+ * "my-default-network-map.pid": "PID3"
+ * }
+ * }
+ * }
+ * */
+ RFC7285JSONMapper mapper = new RFC7285JSONMapper();
+
+ RFC7285Endpoint.PropertyResponse res = new RFC7285Endpoint.PropertyResponse();
+ RFC7285VersionTag vtag = new RFC7285VersionTag("my-default-network-map",
+ "7915dc0290c2705481c491a2b4ffbec482b3cf62");
+ res.meta.netmap_tags.add(vtag);
+
+ String endpoints[] = { "ipv4:192.0.2.34", "ipv4:203.0.113.129" };
+ String properties[] = { "my-default-network-map", "priv:itef-example-prop" };
+ for (String endpoint: endpoints) {
+ res.answer.put(endpoint, new LinkedHashMap<String, Object>());
+ }
+ res.answer.get(endpoints[0]).put(properties[0], "PID1");
+ res.answer.get(endpoints[0]).put(properties[1], new Integer(1));
+ res.answer.get(endpoints[1]).put(properties[0], "PID3");
+
+ String epsrString = mapper.asJSON(res);
+ RFC7285Endpoint.PropertyResponse _res = mapper.asPropertyResponse(epsrString);
+
+ assertCollectionEquals(res.meta.netmap_tags, _res.meta.netmap_tags);
+ for (String endpoint: endpoints) {
+ assertCollectionEquals(res.answer.get(endpoint).entrySet(),
+ _res.answer.get(endpoint).entrySet());
+ }
+ }
+}