yang-gen-code
yang-gen-config
yang-gen-sal
+.ensime
and is available at http://www.eclipse.org/legal/epl-v10.html
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
- odl:use-default-for-reference-types="true">
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
<bean id="provider"
- class="org.opendaylight.alto.core.northbound.impl.AltoNorthboundProvider"
- init-method="init" destroy-method="close">
+ class="org.opendaylight.alto.core.northbound.impl.AltoNorthboundProvider"
+ init-method="init" destroy-method="close">
</bean>
- <service ref="provider" interface="org.opendaylight.alto.core.northbound.api.AltoNorthboundRouter"/>
+
+ <service ref="provider"
+ interface="org.opendaylight.alto.core.northbound.api.AltoNorthboundRouter"
+ odl:type="default"/>
+
</blueprint>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.alto.core</groupId>
+ <artifactId>alto-northbound-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.alto.core</groupId>
+ <artifactId>alto-northbound-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </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>
*/
package org.opendaylight.alto.multicost.impl;
+import org.opendaylight.alto.core.northbound.api.AltoNorthboundRouter;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.multicost.rev170302.MulticostData;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Arrays;
+import java.util.List;
+
public class MulticostProvider {
private static final Logger LOG = LoggerFactory.getLogger(MulticostProvider.class);
+ private MulticostRequestListener listener;
+
+ private ListenerRegistration<?> reg;
+
private final DataBroker dataBroker;
- public MulticostProvider(final DataBroker dataBroker) {
+ private final AltoNorthboundRouter router;
+
+ private MulticostService service;
+
+ private static final DataTreeIdentifier<MulticostData> MULTICOST_DATAROOT;
+
+ private static final String NUMERTICAL = "numerical";
+
+ private static final String ROUTINGCOST = "routingcost";
+
+ private static final String HOPCOUNT = "hopcount";
+
+ private static final String BANDWIDTH = "bandwidth";
+
+ static {
+ InstanceIdentifier<MulticostData> iid = InstanceIdentifier.create(MulticostData.class);
+ MULTICOST_DATAROOT = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, iid);
+ }
+
+ public MulticostProvider(final DataBroker dataBroker,
+ final AltoNorthboundRouter router) {
this.dataBroker = dataBroker;
+ this.router = router;
}
/**
*/
public void init() {
LOG.info("MulticostProvider Session Initiated");
+
+ RFC7285CostType routingcost = new RFC7285CostType(ROUTINGCOST, NUMERTICAL);
+ RFC7285CostType hopcount = new RFC7285CostType(HOPCOUNT, NUMERTICAL);
+ RFC7285CostType bandwidth = new RFC7285CostType(BANDWIDTH, NUMERTICAL);
+
+ List<RFC7285CostType> types = Arrays.asList(routingcost, hopcount, bandwidth);
+
+ service = new MulticostService(types, false);
+ listener = new MulticostRequestListener(dataBroker, service);
+ reg = dataBroker.registerDataTreeChangeListener(MULTICOST_DATAROOT, listener);
}
/**
*/
public void close() {
LOG.info("MulticostProvider Closed");
+ try {
+ reg.close();
+ } catch (Exception e) {
+ // ignore
+ }
}
}
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.multicost.rev170302.MulticostData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.multicost.rev170302.MulticostDataBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class MulticostRequestListener implements DataTreeChangeListener<MulticostData> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MulticostRequestListener.class);
+
+ private final DataBroker db;
+
+ private MulticostService service;
+
+ public MulticostRequestListener(final DataBroker db, final MulticostService service) {
+ this.db = db;
+ this.service = service;
+ }
+
+ private void handleRequest(WriteTransaction tx,
+ InstanceIdentifier<?> iid, DataObject value) {
+ if (iid.getTargetType() != MulticostData.class) {
+ return;
+ }
+ if (!(value instanceof MulticostData)) {
+ return;
+ }
+ try {
+ InstanceIdentifier<MulticostData> miid = iid.firstIdentifierOf(MulticostData.class);
+ MulticostData data = (MulticostData) value;
+ String request = data.getRequestBody();
+
+ String response = service.accept(request);
+
+ MulticostDataBuilder builder = new MulticostDataBuilder(data);
+ builder.setResponseBody(response);
+
+ tx.put(LogicalDatastoreType.OPERATIONAL, miid, builder.build());
+ } catch (Exception e) {
+ LOG.error("Failed to handle request: ", iid.firstKeyOf(MulticostData.class));
+ return;
+ }
+ }
+
+ void dispatch(WriteTransaction tx, DataTreeModification<MulticostData> mod) {
+ InstanceIdentifier<MulticostData> iid = mod.getRootPath().getRootIdentifier();
+ if (mod.getRootNode().getModificationType()
+ .equals(DataObjectModification.ModificationType.DELETE)) {
+ tx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ } else {
+ handleRequest(tx, iid, mod.getRootNode().getDataAfter());
+ }
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<MulticostData>> e) {
+ WriteTransaction tx = db.newWriteOnlyTransaction();
+ try {
+ e.forEach(mod -> dispatch(tx, mod));
+ tx.submit();
+ } catch (Exception exception) {
+ tx.cancel();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.opendaylight.alto.core.northbound.api.exception.AltoBadFormatException;
+import org.opendaylight.alto.core.northbound.api.exception.AltoBasicException;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorInvalidFieldValue;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorInvalideFieldType;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorMissingField;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorSyntax;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
+import org.opendaylight.alto.multicost.impl.data.Condition;
+import org.opendaylight.alto.multicost.impl.data.MulticostRequest;
+import org.opendaylight.alto.multicost.impl.data.MulticostResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+
+class MulticostService {
+
+ private final ImmutableList<RFC7285CostType> types;
+
+ private final boolean testable;
+
+ public MulticostService(final List<RFC7285CostType> types, boolean testable) {
+ this.types = ImmutableList.copyOf(types);
+ this.testable = testable;
+ }
+
+ public String accept(final String input) {
+ try {
+ MulticostRequest req = decode(input);
+
+ MulticostResponse rep = respond(req);
+
+ return encode(rep);
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
+ private ObjectMapper mapper = new ObjectMapper();
+
+ private MulticostResponse respond(MulticostRequest request) {
+ return null;
+ }
+
+ private void checkSemantic(MulticostRequest request) throws AltoBasicException {
+ if ((request.multicostTypes == null) && (request.costType == null)) {
+ /* Either field MUST be specified */
+ throw new AltoErrorMissingField(MulticostRequest.FIELD_MULCOST);
+ }
+ if ((request.multicostTypes != null) && (request.costType != null)) {
+ /* ... but not both */
+ throw new AltoBadFormatException();
+ }
+ if (request.multicostTypes == null) {
+ /* Fallback mode */
+ request.fallbackMode = true;
+ request.multicostTypes = Arrays.asList(request.costType);
+ if (!types.contains(request.costType)) {
+ throw new AltoErrorInvalidFieldValue("cost-type");
+ }
+ } else {
+ boolean allMatch = request.multicostTypes
+ .stream()
+ .allMatch(t -> types.contains(t));
+ if (!allMatch) {
+ throw new AltoErrorInvalidFieldValue(MulticostRequest.FIELD_MULCOST);
+ }
+ }
+ if (!this.testable) {
+ if (request.constraints != null) {
+ throw new AltoErrorInvalideFieldType("constraints");
+ }
+ if (request.orConstraintsRepr != null) {
+ throw new AltoErrorInvalideFieldType(MulticostRequest.FIELD_ORCONSTRAINT);
+ }
+ } else {
+ if ((request.constraints != null) || (request.orConstraintsRepr != null)) {
+ /* ... MUST not both be specified */
+ throw new AltoErrorInvalideFieldType(MulticostRequest.FIELD_ORCONSTRAINT);
+ }
+ if (request.constraints != null) {
+ request.orConstraintsRepr = Arrays.asList(request.constraints);
+ }
+
+ if (request.testableTypes == null) {
+ request.testableTypes = request.multicostTypes;
+ }
+ boolean allMatch = request.testableTypes
+ .stream()
+ .allMatch(t -> types.contains(t));
+ if (!allMatch) {
+ throw new AltoErrorInvalidFieldValue(MulticostRequest.FIELD_TESTABLE);
+ }
+
+ AltoBasicException e;
+ e = new AltoErrorInvalidFieldValue(MulticostRequest.FIELD_ORCONSTRAINT);
+
+ request.orConstraints = request.orConstraintsRepr
+ .stream()
+ .map(l -> l.stream()
+ .map(repr -> Condition.compile(repr, request.testableTypes, e))
+ .collect(Collectors.toList()))
+ .collect(Collectors.toList());
+ }
+ }
+
+ private MulticostRequest decode(String input) throws AltoErrorSyntax {
+ try {
+ MulticostRequest req = mapper.readValue(input, MulticostRequest.class);
+ checkSemantic(req);
+ return req;
+ } catch (Exception e) {
+ throw new AltoErrorSyntax();
+ }
+ }
+
+ private String encode(MulticostResponse response) throws JsonProcessingException {
+ String output = mapper.writeValueAsString(response);
+ return output;
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl.data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import org.opendaylight.alto.core.northbound.api.exception.AltoBasicException;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+public class Condition {
+
+ public static final ImmutableMap<String, BiFunction<Double, Double, Boolean>> OPERATOR_MAP;
+
+ public static final String OP_LTREPR = "lt";
+
+ public static final String OP_LEREPR = "le";
+
+ public static final String OP_EQREPR = "eq";
+
+ public static final String OP_GTREPR = "gt";
+
+ public static final String OP_GEREPR = "ge";
+
+ public static final double PRECISION = 1e-5;
+
+ public static final BiFunction<Double, Double, Boolean> OP_LT;
+ public static final BiFunction<Double, Double, Boolean> OP_LE;
+ public static final BiFunction<Double, Double, Boolean> OP_EQ;
+ public static final BiFunction<Double, Double, Boolean> OP_GT;
+ public static final BiFunction<Double, Double, Boolean> OP_GE;
+
+ static {
+ OP_LT = (x, y) -> (x < y);
+ OP_LE = (x, y) -> (x <= y);
+ OP_EQ = (x, y) -> (Math.abs(y - x) < PRECISION);
+ OP_GT = (x, y) -> (x > y);
+ OP_GE = (x, y) -> (x >= y);
+
+ Map<String, BiFunction<Double, Double, Boolean>> map = Maps.newHashMap();
+ map.put(OP_LTREPR, OP_LT);
+ map.put(OP_LEREPR, OP_LE);
+ map.put(OP_EQREPR, OP_EQ);
+ map.put(OP_GTREPR, OP_GT);
+ map.put(OP_GEREPR, OP_GE);
+
+ OPERATOR_MAP = ImmutableMap.copyOf(map);
+ }
+
+ public static Condition compile(final String repr,
+ List<RFC7285CostType> types,
+ AltoBasicException e) throws AltoBasicException {
+ String[] parts = repr.split(" ");
+ if (parts.length < 2) {
+ throw e;
+ }
+ if (parts.length == 2) {
+ String[] newParts = { "[0]", parts[0], parts[1] };
+ parts = newParts;
+ }
+ if (parts.length > 3) {
+ throw e;
+ }
+ try {
+ String irepr = parts[0].replaceAll("\\s", "");
+ irepr = irepr.substring(1, irepr.length() - 1);
+ int index = Integer.valueOf(irepr);
+ if (index > types.size()) {
+ throw e;
+ }
+ RFC7285CostType type = types.get(index);
+ BiFunction<Double, Double, Boolean> op = OPERATOR_MAP.get(parts[1]);
+ Double bound = Double.valueOf(parts[2]);
+
+ if ((type == null) || (op == null)) {
+ throw e;
+ }
+
+ return new Condition(type, op, bound);
+ } catch (Exception ignore) {
+ throw e;
+ }
+ }
+
+ private Condition(final RFC7285CostType type,
+ final BiFunction<Double, Double, Boolean> operator,
+ final Double bound) {
+ this.type = type;
+ this.operator = operator;
+ this.bound = bound;
+ }
+
+ public final RFC7285CostType type;
+
+ public final BiFunction<Double, Double, Boolean> operator;
+
+ public final Double bound;
+}
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl.data;
+
+import java.util.List;
+
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostMap;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class MulticostRequest extends RFC7285CostMap.Filter {
+
+ public static final String FIELD_MULCOST = "multi-cost-types";
+
+ public static final String FIELD_TESTABLE = "testable-cost-types";
+
+ public static final String FIELD_ORCONSTRAINT = "or-constraints";
+
+ @JsonProperty(FIELD_MULCOST)
+ public List<RFC7285CostType> multicostTypes;
+
+ @JsonProperty(FIELD_TESTABLE)
+ public List<RFC7285CostType> testableTypes;
+
+ @JsonProperty(FIELD_ORCONSTRAINT)
+ public List<List<String>> orConstraintsRepr;
+
+ @JsonIgnore
+ public boolean fallbackMode = false;
+
+ @JsonIgnore
+ public List<List<Condition>> orConstraints;
+
+}
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl.data;
+
+import java.util.List;
+
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostMap;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class MulticostResponse extends RFC7285CostMap {
+
+ public static class Meta extends RFC7285CostMap.Meta {
+
+ public Meta(RFC7285CostMap.Meta base) {
+ this.netmap_tags = base.netmap_tags;
+ this.costType = base.costType;
+ }
+
+ @JsonProperty(MulticostRequest.FIELD_MULCOST)
+ public List<RFC7285CostType> multicostTypes;
+ }
+
+}
and is available at http://www.eclipse.org/legal/epl-v10.html
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
- odl:use-default-for-reference-types="true">
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
<reference id="dataBroker"
- interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
- odl:type="default" />
+ interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+ odl:type="default" />
+
+ <reference id="altonbRouter"
+ interface="org.opendaylight.alto.core.northbound.api.AltoNorthboundRouter"
+ odl:type="default" />
<bean id="provider"
- class="org.opendaylight.alto.multicost.impl.MulticostProvider"
- init-method="init" destroy-method="close">
+ class="org.opendaylight.alto.multicost.impl.MulticostProvider"
+ init-method="init" destroy-method="close">
<argument ref="dataBroker" />
+ <argument ref="altonbRouter" />
</bean>
</blueprint>
--- /dev/null
+/*
+ * Copyright © 2017 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.multicost.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285CostType;
+import org.opendaylight.alto.core.northbound.api.exception.AltoBasicException;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorInvalidFieldValue;
+
+import org.opendaylight.alto.multicost.impl.data.Condition;
+import org.opendaylight.alto.multicost.impl.data.MulticostRequest;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class MulticostServiceTest {
+
+ static final RFC7285CostType c1 = new RFC7285CostType("routincost", "numerical");
+ static final RFC7285CostType c2 = new RFC7285CostType("hopcount", "numerical");
+ static final List<RFC7285CostType> clist = Arrays.asList(c1, c2);
+ static final AltoErrorInvalidFieldValue err = new AltoErrorInvalidFieldValue("test");
+
+ @Test
+ public void testCondition() {
+ String repr;
+ Condition condition;
+
+ repr = "[0] le 100";
+ condition = Condition.compile(repr, clist, err);
+ assertEquals(condition.type, c1);
+ assertEquals(condition.operator, Condition.OP_LE);
+ assertEquals(Math.round(condition.bound), 100);
+
+ repr = "eq 100";
+ condition = Condition.compile(repr, clist, err);
+ assertEquals(condition.type, c1);
+ assertEquals(condition.operator, Condition.OP_EQ);
+ assertEquals(Math.round(condition.bound), 100);
+ }
+
+ void testCheckSemantic(MulticostService service,
+ MulticostRequest request) throws Exception {
+ Method method = MulticostService.class
+ .getDeclaredMethod("checkSemantic",
+ MulticostRequest.class);
+
+ method.setAccessible(true);
+ try {
+ method.invoke(service, request);
+ } catch (InvocationTargetException e) {
+ throw (Exception) e.getCause();
+ }
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testMultipleCostTypes() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.costType = c1;
+ request.multicostTypes = clist;
+
+ MulticostService service = new MulticostService(clist, true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testExtraTestable() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.costType = c1;
+ request.multicostTypes = clist;
+
+ MulticostService service = new MulticostService(clist, true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testMissingCostType() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+
+ MulticostService service = new MulticostService(clist, true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testUnsupportedCostType() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = clist;
+ request.orConstraintsRepr = Arrays.asList(Arrays.asList("le 100"),
+ Arrays.asList("[1] lt 20"));
+
+ MulticostService service = new MulticostService(Arrays.asList(c1), true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testExtraConstraints1() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = clist;
+ request.constraints = Arrays.asList("le 100");
+
+ MulticostService service = new MulticostService(clist, false);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testExtraConstraints2() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = clist;
+ request.orConstraintsRepr = Arrays.asList(Arrays.asList("le 100"),
+ Arrays.asList("[1] lt 20"));
+
+ MulticostService service = new MulticostService(clist, false);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testMultipleConstraints() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = clist;
+ request.constraints = Arrays.asList("le 100");
+ request.orConstraintsRepr = Arrays.asList(Arrays.asList("le 100"),
+ Arrays.asList("[1] lt 20"));
+
+ MulticostService service = new MulticostService(clist, true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testInvalidConstraints() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = clist;
+ request.constraints = Arrays.asList("what 100");
+
+ MulticostService service = new MulticostService(clist, true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test(expected=AltoBasicException.class)
+ public void testUntestableConstraints() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.multicostTypes = Arrays.asList(c1);
+ request.testableTypes = Arrays.asList(c2);
+ request.orConstraintsRepr = Arrays.asList(Arrays.asList("le 100"),
+ Arrays.asList("[1] lt 20"));
+
+ MulticostService service = new MulticostService(Arrays.asList(c1), true);
+
+ testCheckSemantic(service, request);
+ }
+
+ @Test
+ public void testMulticostCheck() throws Exception {
+ MulticostRequest request = new MulticostRequest();
+ request.costType = c1;
+ request.constraints = Arrays.asList("[0] le 100", "[1] le 6");
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ String repr = mapper.writeValueAsString(request);
+ MulticostService service = new MulticostService(clist, true);
+
+ String rep = service.accept(repr);
+ }
+
+ void testConditionFailure(String repr) {
+ Condition.compile(repr, clist, err);
+ }
+
+ @Test(expected=AltoErrorInvalidFieldValue.class)
+ public void test1Parameter() {
+ testConditionFailure("[0]");
+ }
+
+ @Test(expected=AltoErrorInvalidFieldValue.class)
+ public void test4Parameter() {
+ testConditionFailure("[0] lt 100 200");
+ }
+
+ @Test(expected=AltoErrorInvalidFieldValue.class)
+ public void testInvalidIndex() {
+ testConditionFailure("[2] ge 200");
+ }
+
+ @Test(expected=AltoErrorInvalidFieldValue.class)
+ public void testInvalidOp() {
+ testConditionFailure("[0] what 100");
+ }
+
+ @Test(expected=AltoErrorInvalidFieldValue.class)
+ public void testInvalidValue() {
+ testConditionFailure("[0] gt abc");
+ }
+}
<feature name='odl-alto-extension' version='${project.version}'
description='OpenDaylight :: alto :: Extension'>
+ <feature version='${project.version}'>odl-alto-northbound</feature>
<feature version='${project.version}'>odl-alto-nonstandard-types</feature>
<feature version='${project.version}'>odl-alto-nonstandard-service-models</feature>
<feature version='${project.version}'>odl-alto-nonstandard-northbound-route</feature>
<feature version='${project.version}'>odl-alto-spce</feature>
-
- <bundle>mvn:org.opendaylight.alto/multicost-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.alto/multicost-impl/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.alto/incremental-update-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.alto/incremental-update-impl/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.alto/rsade-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.alto/rsade-impl/${project.version}</bundle>
+ <feature version='${project.version}'>odl-alto-multicost</feature>
+ <feature version='${project.version}'>odl-alto-iupd</feature>
+ <feature version='${project.version}'>odl-alto-rsabs</feature>
</feature>
<feature name='odl-alto-spce' version='${project.version}'
<feature name='odl-alto-multicost' version='${project.version}'
description='OpenDaylight :: alto :: Mutlicost support'>
- <!-- new feature in Carbon -->
+ <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version='${project.version}'>odl-alto-northbound</feature>
+
+ <bundle>mvn:org.opendaylight.alto/multicost-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.alto/multicost-impl/${project.version}</bundle>
</feature>
<feature name='odl-alto-iupd' version='${project.version}'
description='OpenDaylight :: alto :: Incremental update'>
- <!-- new feature in Carbon -->
+ <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+
+ <bundle>mvn:org.opendaylight.alto/incremental-update-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.alto/incremental-update-impl/${project.version}</bundle>
</feature>
<feature name='odl-alto-rsabs' version='${project.version}'
description='OpenDaylight :: alto :: Routing state abstraction'>
- <!-- new feature in Carbon -->
+ <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+
+ <bundle>mvn:org.opendaylight.alto/rsade-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.alto/rsade-impl/${project.version}</bundle>
</feature>
</features>
<name>OpenDaylight :: alto :: Extension</name>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-alto-northbound</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-alto-nonstandard-types</artifactId>
<classifier>features</classifier>
</dependency>
<dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>multicost-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>multicost-impl</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>incremental-update-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>incremental-update-impl</artifactId>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-alto-multicost</artifactId>
<version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
</dependency>
<dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>rsade-api</artifactId>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-alto-iupd</artifactId>
<version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
</dependency>
<dependency>
- <groupId>org.opendaylight.alto</groupId>
- <artifactId>rsade-impl</artifactId>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-alto-rsabs</artifactId>
<version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
</dependency>
</dependencies>
</project>
<name>OpenDaylight :: alto :: Incremental update</name>
+ <properties>
+ <mdsal.model.groupId>org.opendaylight.mdsal.model</mdsal.model.groupId>
+ <mdsal.groupId>org.opendaylight.controller</mdsal.groupId>
+ <mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
+ <mdsal.version>1.5.0-SNAPSHOT</mdsal.version>
+ </properties>
+
<dependencies>
- <!-- new feature in Carbon -->
+ <dependency>
+ <groupId>${mdsal.model.groupId}</groupId>
+ <artifactId>odl-mdsal-models</artifactId>
+ <version>${mdsal.model.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${mdsal.groupId}</groupId>
+ <artifactId>odl-mdsal-broker</artifactId>
+ <version>${mdsal.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>incremental-update-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>incremental-update-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
<name>OpenDaylight :: alto :: Mutlicost support</name>
+ <properties>
+ <mdsal.model.groupId>org.opendaylight.mdsal.model</mdsal.model.groupId>
+ <mdsal.groupId>org.opendaylight.controller</mdsal.groupId>
+ <mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
+ <mdsal.version>1.5.0-SNAPSHOT</mdsal.version>
+ </properties>
+
<dependencies>
- <!-- new feature in Carbon -->
+ <dependency>
+ <groupId>${mdsal.model.groupId}</groupId>
+ <artifactId>odl-mdsal-models</artifactId>
+ <version>${mdsal.model.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${mdsal.groupId}</groupId>
+ <artifactId>odl-mdsal-broker</artifactId>
+ <version>${mdsal.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-alto-northbound</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>multicost-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>multicost-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
<name>OpenDaylight :: alto :: Routing state abstraction</name>
+ <properties>
+ <mdsal.model.groupId>org.opendaylight.mdsal.model</mdsal.model.groupId>
+ <mdsal.groupId>org.opendaylight.controller</mdsal.groupId>
+ <mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
+ <mdsal.version>1.5.0-SNAPSHOT</mdsal.version>
+ </properties>
+
<dependencies>
- <!-- new feature in Carbon -->
+ <dependency>
+ <groupId>${mdsal.model.groupId}</groupId>
+ <artifactId>odl-mdsal-models</artifactId>
+ <version>${mdsal.model.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${mdsal.groupId}</groupId>
+ <artifactId>odl-mdsal-broker</artifactId>
+ <version>${mdsal.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>rsade-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.alto</groupId>
+ <artifactId>rsade-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>