Add the northbound exception handler 66/36966/1
authorXiao Lin <linxiao9292@outlook.com>
Tue, 8 Mar 2016 03:54:47 +0000 (11:54 +0800)
committerKai GAO <gaok12@mails.tsinghua.edu.cn>
Thu, 31 Mar 2016 10:33:11 +0000 (18:33 +0800)
Handle ALTO Protocol Errors defined in RFC7285 8.5. Add a class to
generate error information response and implement the checker of
endpoint property service's requests.

 - Exceptions are defined in alto/core/northbound/api/exception

 - Exception handler is in alto/core/northbound/impl/

 - The example of how to use the handler can be found  in
   alto-core/standard-northbound-routes/endpointproperty

Change-Id: Id742d02d92ab6421949fe3ca02f234bec463299f
Signed-off-by: Xiao Lin <linxiao9292@outlook.com>
35 files changed:
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBadFormatException.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBasicException.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalidFieldValue.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalideFieldType.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorMissingField.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorSyntax.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorTestException.java [new file with mode: 0644]
alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/utils/rfc7285/RFC7285ErrorCode.java [new file with mode: 0644]
alto-core/northbound/impl/src/main/java/org/opendaylight/alto/core/northbound/impl/AltoNorthboundApplication.java
alto-core/northbound/impl/src/main/java/org/opendaylight/alto/core/northbound/impl/AltoNorthboundExceptionHandler.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/api/pom.xml [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/api/src/main/yang/alto-nbr-endpointproperty.yang [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/pom.xml [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/default-config.xml [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/maven-metadata-local.xml [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointproperty.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/EndpointpropertyRouteChecker.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModule.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModuleFactory.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/main/yang/alto-northbound-route-endpointproperty-impl.yang [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/impl/src/test/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointpropertyTest.java [new file with mode: 0644]
alto-core/standard-northbound-routes/endpointproperty/pom.xml [new file with mode: 0644]
alto-core/standard-northbound-routes/pom.xml
alto-core/standard-service-models/model-endpointproperty/api/src/main/yang/alto-model-endpointproperty-rfc7285.yang
alto-core/standard-service-models/model-endpointproperty/features/pom.xml
alto-core/standard-service-models/model-endpointproperty/features/src/main/features/features.xml
alto-core/standard-service-models/model-endpointproperty/impl/pom.xml
alto-core/standard-service-models/model-endpointproperty/impl/src/main/java/org/opendaylight/alto/core/impl/endpointproperty/test/AltoEndpointPropertyProvider.java
alto-release-features/pom.xml
alto-release-features/src/main/features/features.xml
test/scripts/endpointpropertymap/endpointpropertymap_input [new file with mode: 0644]
test/scripts/northbound/nbr-endpointproperty-create [new file with mode: 0755]
test/scripts/northbound/query-nbr-endpointproperty [new file with mode: 0755]
test/scripts/northbound/template/endpointproperty-filter [new file with mode: 0644]
test/scripts/northbound/template/nbr-record-endpointproperty [new file with mode: 0644]

diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBadFormatException.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBadFormatException.java
new file mode 100644 (file)
index 0000000..24ac11d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.exception;
+
+import javax.ws.rs.core.Response.Status;
+
+public class AltoBadFormatException extends AltoErrorTestException {
+
+    public AltoBadFormatException() {
+        super(Status.BAD_REQUEST);
+    }
+
+    public AltoBadFormatException(String code) {
+        super(Status.BAD_REQUEST, code);
+    }
+
+    public AltoBadFormatException(String code, String field) {
+        super(Status.BAD_REQUEST, code, field);
+    }
+
+    public AltoBadFormatException(String code, String field, String value) {
+        super(Status.BAD_REQUEST, code, field, value);
+    }
+
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBasicException.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoBasicException.java
new file mode 100644 (file)
index 0000000..4ca2445
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.exception;
+
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.MediaType;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+public class AltoBasicException extends WebApplicationException {
+
+    public AltoBasicException(int status, Object cause) {
+        super(Response.status(status).entity(cause).type(MediaType.ALTO_ERROR).build());
+    }
+
+    public AltoBasicException(Response.Status status, Object cause) {
+        super(Response.status(status).entity(cause).type(MediaType.ALTO_ERROR).build());
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalidFieldValue.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalidFieldValue.java
new file mode 100644 (file)
index 0000000..e2e8d49
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.exception;
+
+import javax.ws.rs.core.Response;
+
+public class AltoErrorInvalidFieldValue extends AltoErrorTestException {
+    public AltoErrorInvalidFieldValue() {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name());
+    }
+
+    public AltoErrorInvalidFieldValue(String field) {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name(), field);
+    }
+
+    public AltoErrorInvalidFieldValue(String field, String value) {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name(), field, value);
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalideFieldType.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorInvalideFieldType.java
new file mode 100644 (file)
index 0000000..49dab3c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.exception;
+
+import javax.ws.rs.core.Response;
+
+public class AltoErrorInvalideFieldType extends AltoErrorTestException {
+    public AltoErrorInvalideFieldType() {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name());
+    }
+
+    public AltoErrorInvalideFieldType(String field) {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name(), field);
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorMissingField.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorMissingField.java
new file mode 100644 (file)
index 0000000..77f5b8e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.exception;
+
+import javax.ws.rs.core.Response;
+
+public class AltoErrorMissingField extends AltoErrorTestException {
+    public AltoErrorMissingField() {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name());
+    }
+
+    public AltoErrorMissingField(String field) {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_MISSING_FIELD.name(), field);
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorSyntax.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorSyntax.java
new file mode 100644 (file)
index 0000000..0d14714
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.exception;
+
+import javax.ws.rs.core.Response;
+
+public class AltoErrorSyntax extends AltoErrorTestException {
+    public AltoErrorSyntax() {
+        super(Response.Status.BAD_REQUEST, ERROR_CODES.E_SYNTAX.name());
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorTestException.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/exception/AltoErrorTestException.java
new file mode 100644 (file)
index 0000000..626b455
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.exception;
+import javax.ws.rs.core.Response;
+
+public class AltoErrorTestException extends AltoBasicException {
+    public static final String TEMPLATE_EMPTY = "{}";
+    public static final String TEMPLATE_CODE =
+            "{\"meta\":{\"code\":\"%s\"}}";
+    public static final String TEMPLATE_CODE_FIELD =
+            "{\"meta\":{\"code\":\"%s\",\"field\":\"%s\"}}";
+    public static final String TEMPLATE_CODE_FIELD_VALUE =
+            "{\"meta\":{\"code\":\"%s\",\"field\":\"%s\",\"value\":\"%s\"}}";
+
+    public enum ERROR_CODES {
+      E_MISSING_FIELD, E_SYNTAX, E_INVALID_FIELD_TYPE, E_INVALID_FIELD_VALUE, E_INVALID_CLIENT_IP
+    }
+
+    public AltoErrorTestException(Response.Status status) {
+        super(status, "{}");
+    }
+
+    public AltoErrorTestException(Response.Status status, String code) {
+        super(status, String.format(TEMPLATE_CODE, code));
+    }
+
+    public AltoErrorTestException(Response.Status status, String code, String field) {
+        super(status, String.format(TEMPLATE_CODE_FIELD, code, field));
+    }
+
+    public AltoErrorTestException(Response.Status status, String code, String field, String value) {
+        super(status, String.format(TEMPLATE_CODE_FIELD_VALUE, code, field, value));
+    }
+}
diff --git a/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/utils/rfc7285/RFC7285ErrorCode.java b/alto-core/northbound/api/src/main/java/org/opendaylight/alto/core/northbound/api/utils/rfc7285/RFC7285ErrorCode.java
new file mode 100644 (file)
index 0000000..0f85b7e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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 RFC7285ErrorCode {
+    public static String E_SYNTAX = "E_SYNTAX";
+    public static String E_MISSING_FIELD = "E_MISSING_FIELD";
+    public static String E_INVALID_FIELD_TYPE = "E_INVALID_FIELD_TYPE";
+    public static String E_INVALID_FIELD_VALUE = "E_INVALID_FIELD_VALUE";
+}
index 2377241d818f0cc89318c3a666bd4134ea2d45bc..8e45ec9731d58cfba491e89cfb42d1292ec2539a 100644 (file)
@@ -17,6 +17,7 @@ public class AltoNorthboundApplication extends Application {
     public Set<Class<?>> getClasses() {
         Set<Class<?>> classes = new HashSet<Class<?>>();
         classes.add(AltoNorthbound.class);
+        classes.add(AltoNorthboundExceptionHandler.class);
         return classes;
     }
 }
diff --git a/alto-core/northbound/impl/src/main/java/org/opendaylight/alto/core/northbound/impl/AltoNorthboundExceptionHandler.java b/alto-core/northbound/impl/src/main/java/org/opendaylight/alto/core/northbound/impl/AltoNorthboundExceptionHandler.java
new file mode 100644 (file)
index 0000000..36394d2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.impl;
+
+import org.opendaylight.alto.core.northbound.api.exception.AltoBasicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+public class AltoNorthboundExceptionHandler implements ExceptionMapper<Exception> {
+
+    private static final Logger logger = LoggerFactory
+        .getLogger(AltoNorthboundExceptionHandler.class);
+
+    @Override
+    public Response toResponse(Exception e) {
+        logger.info("begin exception handle: " + e.toString());
+        logger.info("exception type: " + e.getClass().toString());
+        if (e instanceof AltoBasicException) {
+            return ((AltoBasicException) e).getResponse();
+        }
+        if (e instanceof WebApplicationException) {
+            return ((WebApplicationException) e).getResponse();
+        }
+        return Response.status(Response
+            .Status.INTERNAL_SERVER_ERROR)
+            .type(org.opendaylight.alto.core.northbound.api.utils.rfc7285.MediaType.ALTO_ERROR).build();
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/api/pom.xml b/alto-core/standard-northbound-routes/endpointproperty/api/pom.xml
new file mode 100644 (file)
index 0000000..722d6fa
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright Â© 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-parent</artifactId>
+        <version>0.5.0-SNAPSHOT</version>
+        <relativePath></relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.alto.core</groupId>
+    <artifactId>alto-northbound-route-endpointproperty-api</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>alto-service-model-endpointproperty-api</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>servlet-api</artifactId>
+            <version>2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>ietf-inet-types-2013-07-15</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/alto-core/standard-northbound-routes/endpointproperty/api/src/main/yang/alto-nbr-endpointproperty.yang b/alto-core/standard-northbound-routes/endpointproperty/api/src/main/yang/alto-nbr-endpointproperty.yang
new file mode 100644 (file)
index 0000000..27a61c4
--- /dev/null
@@ -0,0 +1,30 @@
+module alto-nbr-endpointproperty {
+    yang-version 1;
+    namespace "urn:opendaylight:alto:core:northbound:route:endpointproperty";
+    prefix "alto-nbr-endpointproperty";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import ietf-inet-types { prefix ietf-inet; revision-date 2013-07-15; }
+
+    organization "Yale University";
+
+    contact "alto-dev@lists.opendaylight.org";
+
+    revision "2015-10-21" {
+        description "Initial revision of endpointproperty model";
+    }
+
+    container "records" {
+        list "record" {
+            key "path";
+
+            leaf "path" {
+                type ietf-inet:uri;
+            }
+
+            leaf "resource-iid" {
+                type instance-identifier;
+            }
+        }
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/pom.xml b/alto-core/standard-northbound-routes/endpointproperty/impl/pom.xml
new file mode 100644 (file)
index 0000000..4fdbcda
--- /dev/null
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-parent</artifactId>
+        <version>0.5.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.alto.core</groupId>
+    <artifactId>alto-northbound-route-endpointproperty-impl</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>alto-northbound-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>alto-northbound-impl</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>alto-service-model-endpointproperty-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>alto-northbound-route-endpointproperty-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>ietf-inet-types-2013-07-15</artifactId>
+        </dependency>
+
+        <!-- Testing Dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </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.datatype</groupId>
+            <artifactId>jackson-datatype-json-org</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+        </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>servlet-api</artifactId>
+            <version>2.5</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>${bundle.plugin.version}</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Import-Package>*,com.sun.jersey.spi.container.servlet, org.eclipse.jetty.servlets</Import-Package>
+                        <Web-ContextPath>/alto</Web-ContextPath>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/default-config.xml b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..052794d
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright Â© 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
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:alto:core:northbound:route:endpointproperty:impl?module=alto-northbound-route-endpointproperty-impl&amp;revision=2015-10-21</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+      <capability>urn:opendaylight:alto:core:northbound?module=alto-northbound&amp;revision=2015-10-21</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:alto:core:northbound:route:endpointproperty:impl">prefix:alto-northbound-route-endpointproperty-impl</type>
+          <name>alto-northbound-route-endpointproperty</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+          <alto-northbound-router>
+            <type xmlns:alto-northbound-router="urn:opendaylight:alto:core:northbound">alto-northbound-router:alto-northbound-router</type>
+            <name>alto-northbound-router</name>
+          </alto-northbound-router>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/maven-metadata-local.xml b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/config/maven-metadata-local.xml
new file mode 100644 (file)
index 0000000..f403e79
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata modelVersion="1.1.0">
+  <groupId>org.opendaylight.alto.core</groupId>
+  <artifactId>alto-northbound-impl</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <versioning>
+    <snapshot>
+      <localCopy>true</localCopy>
+    </snapshot>
+    <lastUpdated>20151105030453</lastUpdated>
+    <snapshotVersions>
+      <snapshotVersion>
+        <classifier>config</classifier>
+        <extension>xml</extension>
+        <value>0.2.0-SNAPSHOT</value>
+        <updated>20151105030453</updated>
+      </snapshotVersion>
+    </snapshotVersions>
+  </versioning>
+</metadata>
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointproperty.java b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointproperty.java
new file mode 100644 (file)
index 0000000..e23cb14
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * 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.route.endpointproperty.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Optional;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorInvalidFieldValue;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285EndpointPropertyMap;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285VersionTag;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.alto.core.northbound.api.AltoNorthboundRoute;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.alto.core.northbound.api.AltoNorthboundRouter;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.rev151021.records.Record;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.rev151021.records.RecordKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.resourcepool.rev150921.context.Resource;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.resourcepool.rev150921.context.resource.ContextTag;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.resourcepool.rev150921.context.resource.ContextTagKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.SpecificEndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.GlobalEndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.rev151021.Records;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.AltoModelEndpointpropertyService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.ResourceTypeEndpointproperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.alto.request.endpointproperty.request.EndpointpropertyRequestBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.alto.response.endpointproperty.response.EndpointpropertyResponse;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.endpointproperty.request.data.EndpointpropertyParamsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.Ipv4AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.Ipv6AddressData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.EndpointpropertyFilterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.EndpointFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.EndpointFilterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.PropertyFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.PropertyFilterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.EndpointPropertyMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.EndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.Properties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.Source;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.properties.PropertyValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.EndpointpropertyFilterDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.endpoint.filter.address.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.endpoint.filter.address.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.property.filter.property.InputGlobalPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.property.filter.property.InputResourceSpecificPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.EndpointPropertymapData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.container.property.OutputGlobalProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.container.property.OutputResourceSpecificProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.value.PidName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.typed.address.data.Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.typed.property.data.Property;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.concurrent.Future;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+public class AltoNorthboundRouteEndpointproperty implements BindingAwareProvider, AutoCloseable, AltoNorthboundRoute {
+    public static final String ALTO_ENDPOINTPROPERTY_FILTER = "application/alto-endpointpropparams+json";
+    public static final String ALTO_ENDPOINTPROPERTY = "application/alto-endpointprop+json";
+    public static final String FIELD_PROPERTIES = "properties";
+    public static final String FIELD_ENDPOINTS = "endpoints";
+    public static final String IPv4_PREFIX = "ipv4:";
+    public static final String IPv6_PREFIX = "ipv6:";
+    public static final String PRIV_PREFIX = "priv:";
+
+    private ObjectMapper mapper = new ObjectMapper();
+    private static final Logger LOG = LoggerFactory.getLogger(AltoNorthboundRouteEndpointproperty.class);
+    private static DataBroker m_dataBroker = null;
+    private AltoNorthboundRouter m_router = null;
+
+    private  static AltoModelEndpointpropertyService mapService = null;
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        m_dataBroker = session.getSALService(DataBroker.class);
+        if (m_dataBroker == null) {
+            LOG.error("Failed to init: data broker is null");
+        }
+        mapService = session.getRpcService(AltoModelEndpointpropertyService.class);
+        LOG.info("AltoNorthboundRouteEndpointProperty initiated");
+    }
+
+    public void register(AltoNorthboundRouter router) {
+        m_router = router;
+        m_router.addRoute("endpointproperty", new AltoNorthboundRouteEndpointproperty());
+    }
+
+    @Override
+    public void close() {
+        m_router.removeRoute("endpointproperty");
+    }
+
+    @Path("{path}")
+    @POST
+    @Consumes({ALTO_ENDPOINTPROPERTY_FILTER})
+    @Produces({ALTO_ENDPOINTPROPERTY, ALTO_ERROR})
+    public Response getEndpointProperty(@PathParam("path") String path, String content) {
+        JsonNode filterNode = EndpointpropertyRouteChecker.checkJsonSyntax(content);
+        JsonNode _properties = filterNode.get(FIELD_PROPERTIES);
+        EndpointpropertyRouteChecker.checkMissing(_properties, FIELD_PROPERTIES);
+        EndpointpropertyRouteChecker.checkList(_properties, FIELD_PROPERTIES);
+
+        JsonNode _endpoints = filterNode.get(FIELD_ENDPOINTS);
+        EndpointpropertyRouteChecker.checkMissing(_endpoints, FIELD_ENDPOINTS);
+        EndpointpropertyRouteChecker.checkList(_endpoints, FIELD_ENDPOINTS);
+
+        QueryInput input = prepareInput(path, _properties.elements(), _endpoints.elements());
+        LOG.info(input.toString());
+
+        Future<RpcResult<QueryOutput>> outputFuture = mapService.query(input);
+        QueryOutput output = null;
+        try {
+            output = outputFuture.get().getResult();
+        } catch (Exception e) {
+            LOG.warn("get output failed:" , e);
+        }
+        Response response = null;
+        try {
+            response = buildOutput(input, output);
+        }
+        catch (Exception E){
+
+        }
+        if(response != null)
+            return response;
+        else
+            return Response.status(404).build();
+    }
+
+    private Property constructProperty (String property) {
+        try {
+            if (property.contains(".")) {
+                return new InputResourceSpecificPropertyBuilder()
+                        .setResourceSpecificProperty(
+                                new SpecificEndpointProperty(property)).build();
+            } else if (property.equals(PRIV_PREFIX)) {
+                throw new AltoErrorInvalidFieldValue(FIELD_PROPERTIES, property);
+            } else {
+                return new InputGlobalPropertyBuilder()
+                        .setGlobalProperty(
+                                new GlobalEndpointProperty(property)).build();
+            }
+        }
+        catch (IllegalArgumentException E) {
+            throw new AltoErrorInvalidFieldValue(FIELD_PROPERTIES, property);
+        }
+    }
+
+    private Address constructAddress (String address) {
+        try {
+            if (address.contains(IPv4_PREFIX)) {
+                return new Ipv4Builder().setIpv4(
+                    new Ipv4Address(address.replace(IPv4_PREFIX, ""))).build();
+            } else if (address.contains(IPv6_PREFIX)) {
+                return new Ipv6Builder().setIpv6(
+                    new Ipv6Address(address.replace(IPv6_PREFIX, ""))).build();
+            } else {
+                throw new AltoErrorInvalidFieldValue(FIELD_ENDPOINTS, address);
+            }
+        }
+        catch (IllegalArgumentException E) {
+            throw new AltoErrorInvalidFieldValue(FIELD_PROPERTIES, address);
+        }
+    }
+
+    protected List<PropertyFilter> constructListPropertyFilter(Iterator<JsonNode> properties) {
+        List<PropertyFilter> listPropertyFilter = new LinkedList<>();
+        while (properties.hasNext()) {
+            listPropertyFilter.add(
+                    new PropertyFilterBuilder()
+                            .setProperty(constructProperty(properties.next().asText())).build());
+        }
+        return listPropertyFilter;
+    }
+
+    protected List<EndpointFilter> constructListEndpointFilter(Iterator<JsonNode> endpoints) {
+        List<EndpointFilter> listEndpointFilter = new LinkedList<>();
+        while (endpoints.hasNext()) {
+            listEndpointFilter.add(
+                    new EndpointFilterBuilder()
+                            .setAddress(constructAddress(endpoints.next().asText())).build());
+        }
+        return listEndpointFilter;
+    }
+
+    protected QueryInput buildQueryInput(InstanceIdentifier<ContextTag> ctagIID,
+                                         List<PropertyFilter> listPropertyFilter,
+                                         List<EndpointFilter> listEndpointFilter ) {
+        return new QueryInputBuilder()
+                .setType(ResourceTypeEndpointproperty.class)
+                .setServiceReference(ctagIID)
+                .setRequest(
+                        new EndpointpropertyRequestBuilder()
+                                .setEndpointpropertyParams(
+                                        new EndpointpropertyParamsBuilder()
+                                                .setFilter(
+                                                        new EndpointpropertyFilterDataBuilder()
+                                                                .setEndpointpropertyFilter(
+                                                                        new EndpointpropertyFilterBuilder()
+                                                                                .setEndpointFilter(listEndpointFilter)
+                                                                                .setPropertyFilter(listPropertyFilter)
+                                                                                .build())
+                                                                .build())
+                                                .build())
+                                .build())
+                .build();
+    }
+
+    protected QueryInput prepareInput(String path, Iterator<JsonNode> properties, Iterator<JsonNode> endpoints) {
+        ReadOnlyTransaction rtx = m_dataBroker.newReadOnlyTransaction();
+        InstanceIdentifier<ContextTag> ctagIID = getResourceByPath(path, rtx);
+        if(ctagIID == null){
+            return null;
+        }
+        List<PropertyFilter> listPropertyFilter = constructListPropertyFilter(properties);
+        List<EndpointFilter> listEndpointFilter = constructListEndpointFilter(endpoints);
+        return buildQueryInput(ctagIID, listPropertyFilter, listEndpointFilter);
+    }
+
+    public InstanceIdentifier<ContextTag> getResourceByPath(String path, ReadOnlyTransaction transaction){
+        //get iid from (list Records)
+        InstanceIdentifier<Record> recordIID = InstanceIdentifier.builder(Records.class)
+                .child(Record.class, new RecordKey(new Uri(path))).build();
+        Future<Optional<Record>> recordFuture = transaction.read(LogicalDatastoreType.CONFIGURATION, recordIID);
+        Optional<Record> recordOptional = null;
+        try {
+            recordOptional = recordFuture.get();
+        } catch(Exception e){
+            LOG.error("Reading Record failed", e);
+            return null;
+        }
+        //get resourceIID from nbr-endpointproperty.yang
+        InstanceIdentifier<?> record2resourceIID = null;
+        if(recordOptional.isPresent()) {
+            record2resourceIID = recordOptional.get().getResourceIid();
+        }
+        InstanceIdentifier<Resource> resourceIID = (InstanceIdentifier<Resource>)record2resourceIID;
+        Future<Optional<Resource>> resourceFuture = transaction.read(LogicalDatastoreType.OPERATIONAL, resourceIID);
+        Optional<Resource> resourceOptional = null;
+        try{
+            resourceOptional = resourceFuture.get();
+        }
+        catch(Exception e){
+            LOG.error("Read resource failed:", e);
+            return null;
+        }
+        Resource resource = null;
+        if(resourceOptional.isPresent())
+            resource = resourceOptional.get();
+        InstanceIdentifier<ContextTag> finalresourceIID = resourceIID
+                .child(ContextTag.class, new ContextTagKey(resource.getDefaultTag()));
+        return finalresourceIID;
+    }
+
+    protected  String getAddressValue(Address address){
+        String addressValue = null;
+        if(address instanceof Ipv4AddressData){
+            Ipv4AddressData ipv4 = (Ipv4AddressData)address;
+            addressValue = IPv4_PREFIX + ipv4.getIpv4().getValue();
+        }else if(address instanceof Ipv6AddressData){
+            Ipv6AddressData ipv6 = (Ipv6AddressData)address;
+            addressValue = IPv6_PREFIX + ipv6.getIpv6().getValue();
+        }
+        return addressValue;
+    }
+
+    protected Response buildOutput(QueryInput input, QueryOutput output) throws JsonProcessingException {
+        EndpointpropertyResponse epResponse = (EndpointpropertyResponse) output.getResponse();
+        EndpointPropertymapData epMapData = (EndpointPropertymapData) epResponse.getEndpointpropertyData();
+        EndpointPropertyMap epMap = epMapData.getEndpointPropertyMap();
+        List<EndpointProperty> linkEndpointProperty = epMap.getEndpointProperty();
+        Map<String, Map<String, String>> endpointpropertyMap = new HashMap<>();
+        for (EndpointProperty ep: linkEndpointProperty) {
+            Map<String, String> propertyMap = new HashMap<>();
+            Source source = ep.getSource();
+            String endpointSourceAddress = getAddressValue(source.getAddress());
+            List<Properties>
+                    properties = ep.getProperties();
+            for (Properties property: properties) {
+                PropertyValue propertyValue = property.getPropertyValue();
+                if (property.getPropertyContainer().getProperty() instanceof OutputResourceSpecificProperty)
+                    propertyMap.put(((OutputResourceSpecificProperty)property.getPropertyContainer().getProperty()).getResourceSpecificProperty().getValue(), ((PidName)propertyValue).getValue().getValue());
+                else {
+                    propertyMap.put(((OutputGlobalProperty)property.getPropertyContainer().getProperty()).getGlobalProperty().getValue(), ((PidName)propertyValue).getValue().getValue());
+                }
+            }
+
+            endpointpropertyMap.put(endpointSourceAddress, propertyMap);
+        }
+
+        RFC7285EndpointPropertyMap rfcEPM= new RFC7285EndpointPropertyMap();
+        rfcEPM.map = endpointpropertyMap;
+        rfcEPM.meta = buildMeta(input.getServiceReference());
+        String responseString = mapper.writeValueAsString(rfcEPM);
+
+        return Response.ok(responseString, ALTO_ENDPOINTPROPERTY).build();
+    }
+
+    protected RFC7285EndpointPropertyMap.Meta buildMeta(InstanceIdentifier<?> iid) {
+        RFC7285EndpointPropertyMap.Meta meta = new RFC7285EndpointPropertyMap.Meta();
+        RFC7285VersionTag vtag = new RFC7285VersionTag();
+        vtag.rid = iid.firstKeyOf(Resource.class).getResourceId().getValue();
+        vtag.tag = iid.firstKeyOf(ContextTag.class).getTag().getValue();
+        meta.netmap_tags = new LinkedList<>();
+        meta.netmap_tags.add(vtag);
+        return meta;
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/EndpointpropertyRouteChecker.java b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/EndpointpropertyRouteChecker.java
new file mode 100644 (file)
index 0000000..dd43634
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.route.endpointproperty.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+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 java.io.IOException;
+
+public class EndpointpropertyRouteChecker {
+
+    public static final String FIELD_PROPERTIES = "properties";
+
+    public static void checkMissing(JsonNode target, String field) {
+        if (target == null) {
+            throw new AltoErrorMissingField(field);
+        }
+    }
+
+    public static void checkList(JsonNode list, String field) {
+        if (!list.isArray()) {
+            throw new AltoErrorInvalideFieldType(field);
+        }
+    }
+
+    public static JsonNode checkJsonSyntax(String content) {
+        JsonNode jsonContent;
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            jsonContent = mapper.readTree(content);
+        }
+        catch (IOException e) {
+            throw new AltoErrorSyntax();
+        }
+        if (null==jsonContent) {
+            throw new AltoErrorSyntax();
+        } else if (jsonContent.isNull()) {
+            throw new AltoErrorMissingField(AltoNorthboundRouteEndpointproperty.FIELD_PROPERTIES);
+        } else {
+            return jsonContent;
+        }
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModule.java b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModule.java
new file mode 100644 (file)
index 0000000..74a61b4
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.impl.rev151021;
+
+import org.opendaylight.alto.core.northbound.route.endpointproperty.impl.AltoNorthboundRouteEndpointproperty;
+
+public class AltoNorthboundRouteEndpointpropertyModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.impl.rev151021.AbstractAltoNorthboundRouteEndpointpropertyModule {
+    public AltoNorthboundRouteEndpointpropertyModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public AltoNorthboundRouteEndpointpropertyModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.impl.rev151021.AltoNorthboundRouteEndpointpropertyModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        AltoNorthboundRouteEndpointproperty endpointproperty = new AltoNorthboundRouteEndpointproperty();
+        getBrokerDependency().registerProvider(endpointproperty);
+        endpointproperty.register(getAltoNorthboundRouterDependency());
+        return endpointproperty;
+    }
+
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModuleFactory.java b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/alto/core/northbound/route/endpointproperty/impl/rev151021/AltoNorthboundRouteEndpointpropertyModuleFactory.java
new file mode 100644 (file)
index 0000000..814c533
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: alto-northbound-route-endpointproperty-impl yang module local name: alto-northbound-route-endpointproperty-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Dec 08 16:37:14 CST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.impl.rev151021;
+public class AltoNorthboundRouteEndpointpropertyModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.northbound.route.endpointproperty.impl.rev151021.AbstractAltoNorthboundRouteEndpointpropertyModuleFactory {
+
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/yang/alto-northbound-route-endpointproperty-impl.yang b/alto-core/standard-northbound-routes/endpointproperty/impl/src/main/yang/alto-northbound-route-endpointproperty-impl.yang
new file mode 100644 (file)
index 0000000..fc7429f
--- /dev/null
@@ -0,0 +1,46 @@
+module alto-northbound-route-endpointproperty-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:alto:core:northbound:route:endpointproperty:impl";
+    prefix "alto-northbound-router-endpointproperty-impl";
+
+    import alto-northbound { prefix alto-northbound; revision-date 2015-10-21; }
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for northbound project";
+
+    revision "2015-10-21" {
+        description
+            "Initial revision";
+    }
+
+    identity alto-northbound-route-endpointproperty-impl {
+        base config:module-type;
+        config:java-name-prefix AltoNorthboundRouteEndpointproperty;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case alto-northbound-route-endpointproperty {
+            when "/config:modules/config:module/config:type = 'alto-northbound-route-endpointproperty-impl'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+
+            container alto-northbound-router {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity alto-northbound:alto-northbound-router;
+                    }
+                }
+            }
+        }
+
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/impl/src/test/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointpropertyTest.java b/alto-core/standard-northbound-routes/endpointproperty/impl/src/test/java/org/opendaylight/alto/core/northbound/route/endpointproperty/impl/AltoNorthboundRouteEndpointpropertyTest.java
new file mode 100644 (file)
index 0000000..b4e6b3b
--- /dev/null
@@ -0,0 +1,315 @@
+package org.opendaylight.alto.core.northbound.route.endpointproperty.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285EndpointPropertyMap;
+import org.opendaylight.alto.core.northbound.api.utils.rfc7285.RFC7285VersionTag;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.resourcepool.rev150921.context.resource.ContextTag;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.GlobalEndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.PidName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.SpecificEndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.AltoModelEndpointpropertyService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.ResourceTypeEndpointproperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.alto.request.endpointproperty.request.EndpointpropertyRequest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.alto.response.endpointproperty.response.EndpointpropertyResponseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.endpointproperty.request.data.EndpointpropertyParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.EndpointFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.EndpointFilterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.PropertyFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.PropertyFilterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.EndpointPropertyMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.EndpointProperty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.EndpointPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.Properties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.PropertiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.Source;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.properties.PropertyContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.EndpointpropertyFilterData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.endpoint.filter.address.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.property.filter.property.InputGlobalPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.property.filter.property.InputResourceSpecificPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.EndpointPropertymapDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.container.property.OutputGlobalPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.container.property.OutputResourceSpecificPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.value.PidNameBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import javax.annotation.Nonnull;
+import javax.ws.rs.core.Response;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.anyObject;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AltoNorthboundRouteEndpointpropertyTest {
+    static String ENDPOINTPROPERTY_FILTER = "{\"properties\" : [ \"my-default-networkmap.pid\","
+                  + "                   \"priv:ietf-example-prop\" ],"
+                  + "  \"endpoints\"  : [ \"ipv4:192.0.2.34\","
+                  + "                   \"ipv4:203.0.113.129\" ]" + "}";
+    static String PATH = "test-model-endpointproperty";
+    static String RESOURCE_SPECIFIC_PROPERTY = "my-default-networkmap.pid";
+    static String GLOBAL_PROPERTY = "priv:ietf-example-prop";
+    static String THE_FIRST_IPv4_ADDRESS = "192.0.2.34";
+    static String THE_SECOND_IPv4_ADDRESS = "203.0.113.129";
+    static String DEFAULT_NETWORKMAP = "my-default-network-map.pid";
+    static String DEFAULT_GLOBAL_PROPERTY_NAME = "priv:ietf-example-prop";
+    static String TARGET_ENDPOINT_PREOPERTIES =
+          "{\"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\" }}";
+    static String FIELD_ENDPOINT_PROPERTIES = "endpoint-properties";
+    static String DEFAULT_RID = "test-model-endpointproperty";
+    static String DEFAULT_TAG = "75ed013b3cb58f896e839582504f622838ce670f";
+
+    final AltoNorthboundRouteEndpointproperty anbre= new AltoNorthboundRouteEndpointproperty();
+
+    @Test
+    public void testPrepareInput() {
+
+        AltoNorthboundRouteEndpointproperty anbreSpy = spy(anbre);
+        BindingAwareBroker.ProviderContext session = mock(BindingAwareBroker.ProviderContext.class);
+        InstanceIdentifier<ContextTag> ctagIID = InstanceIdentifier.create(ContextTag.class);
+        JsonNode filterNode = EndpointpropertyRouteChecker.checkJsonSyntax(ENDPOINTPROPERTY_FILTER);
+        JsonNode _properties = filterNode.get(AltoNorthboundRouteEndpointproperty.FIELD_PROPERTIES);
+        JsonNode _endpoints = filterNode.get(AltoNorthboundRouteEndpointproperty.FIELD_ENDPOINTS);
+
+        doReturn(ctagIID)
+            .when(anbreSpy)
+            .getResourceByPath(eq(PATH), (ReadOnlyTransaction) anyObject());
+        when(session.getSALService(DataBroker.class)).thenReturn(new DataBroker() {
+            @Override public ReadOnlyTransaction newReadOnlyTransaction() {
+                return null;
+            }
+
+            @Override public ReadWriteTransaction newReadWriteTransaction() {
+                return null;
+            }
+
+            @Override public WriteTransaction newWriteOnlyTransaction() {
+                return null;
+            }
+
+            @Override public ListenerRegistration<DataChangeListener> registerDataChangeListener(
+                LogicalDatastoreType logicalDatastoreType, InstanceIdentifier<?> instanceIdentifier,
+                DataChangeListener dataChangeListener, DataChangeScope dataChangeScope) {
+                return null;
+            }
+
+            @Override public BindingTransactionChain createTransactionChain(
+                TransactionChainListener transactionChainListener) {
+                return null;
+            }
+
+            @Nonnull @Override
+            public <T extends DataObject, L extends DataTreeChangeListener<T>> ListenerRegistration<L> registerDataTreeChangeListener(
+                @Nonnull DataTreeIdentifier<T> dataTreeIdentifier, @Nonnull L l) {
+                return null;
+            }
+        });
+
+        anbreSpy.onSessionInitiated(session);
+        QueryInput input = anbreSpy.prepareInput(PATH, _properties.elements(), _endpoints.elements());
+        EndpointpropertyRequest request = (EndpointpropertyRequest)input.getRequest();
+        EndpointpropertyParams params = request.getEndpointpropertyParams();
+        List<PropertyFilter> listProperty = ((EndpointpropertyFilterData) params.getFilter()).getEndpointpropertyFilter().getPropertyFilter();
+        List<EndpointFilter> listEndpoint = ((EndpointpropertyFilterData) params.getFilter()).getEndpointpropertyFilter().getEndpointFilter();
+        List<PropertyFilter> expectedListProperty = new LinkedList<>();
+        List<EndpointFilter> expectedListEndpoint = new LinkedList<>();
+
+        expectedListProperty.add(new PropertyFilterBuilder()
+            .setProperty(new InputResourceSpecificPropertyBuilder()
+                .setResourceSpecificProperty(
+                    new SpecificEndpointProperty(RESOURCE_SPECIFIC_PROPERTY))
+                .build())
+            .build()
+        );
+        expectedListProperty.add(new PropertyFilterBuilder()
+            .setProperty(new InputGlobalPropertyBuilder()
+                .setGlobalProperty(
+                    new GlobalEndpointProperty(GLOBAL_PROPERTY))
+                .build())
+            .build()
+        );
+
+        expectedListEndpoint.add(new EndpointFilterBuilder()
+            .setAddress(
+                new Ipv4Builder()
+                    .setIpv4(new Ipv4Address(THE_FIRST_IPv4_ADDRESS))
+                    .build())
+            .build()
+        );
+        expectedListEndpoint.add(new EndpointFilterBuilder()
+            .setAddress(
+                new Ipv4Builder()
+                    .setIpv4(new Ipv4Address(THE_SECOND_IPv4_ADDRESS))
+                    .build())
+            .build()
+        );
+
+        assertEquals(expectedListProperty, listProperty);
+        assertEquals(expectedListEndpoint, listEndpoint);
+    }
+
+    @Test
+    public void testBuildOutput() throws IOException, ExecutionException, InterruptedException{
+        AltoNorthboundRouteEndpointproperty anbreSpy = spy(anbre);
+        BindingAwareBroker.ProviderContext session = mock(BindingAwareBroker.ProviderContext.class);
+        InstanceIdentifier<ContextTag> ctagIID = InstanceIdentifier.create(ContextTag.class);
+
+        AltoModelEndpointpropertyService epService = mock(AltoModelEndpointpropertyService.class);
+        Future<RpcResult<QueryOutput>> future = mock(Future.class);
+        RpcResult<QueryOutput> rpcResult =mock(RpcResult.class);
+
+        LinkedList<EndpointProperty> eppist = new LinkedList<>();
+
+        SourceBuilder sourceBuilder = new SourceBuilder();
+        Source THE_FIRST_SOURCE = sourceBuilder.setAddress(
+            new Ipv4Builder()
+                .setIpv4(new Ipv4Address(THE_FIRST_IPv4_ADDRESS))
+                .build())
+            .build();
+        Source THE_SECOND_SOURCE = sourceBuilder.setAddress(
+            new Ipv4Builder()
+                .setIpv4(new Ipv4Address(THE_SECOND_IPv4_ADDRESS))
+                .build())
+            .build();
+
+        EndpointPropertyBuilder epBuilder = new EndpointPropertyBuilder();
+        List<Properties> THE_FIRST_LIST_PROPERTIES = new LinkedList<>();
+        List<Properties> THE_SECOND_LIST_PROPERTIES = new LinkedList<>();
+
+        PropertiesBuilder propertiesBuilder = new PropertiesBuilder();
+        PropertyContainerBuilder pcBuilder = new PropertyContainerBuilder();
+
+        PidName pidName = new PidName("PID1");
+        PidNameBuilder pidNameBuilder = new PidNameBuilder();
+        pidNameBuilder.setValue(pidName);
+        pcBuilder.setProperty(
+            new OutputResourceSpecificPropertyBuilder()
+                .setResourceSpecificProperty(new SpecificEndpointProperty(DEFAULT_NETWORKMAP)).build());
+        propertiesBuilder.setPropertyContainer(pcBuilder.build()).setPropertyValue(pidNameBuilder.build());
+        THE_FIRST_LIST_PROPERTIES.add(propertiesBuilder.build());
+
+        pcBuilder.setProperty(
+            new OutputGlobalPropertyBuilder()
+                .setGlobalProperty(new GlobalEndpointProperty(DEFAULT_GLOBAL_PROPERTY_NAME))
+                .build()
+        );
+        PidName fackGlobalProperty = new PidName("1");
+        pidNameBuilder.setValue(fackGlobalProperty);
+        propertiesBuilder.setPropertyContainer(pcBuilder.build()).setPropertyValue(pidNameBuilder.build());
+        THE_FIRST_LIST_PROPERTIES.add(propertiesBuilder.build());
+
+        pidName = new PidName("PID3");
+        pidNameBuilder.setValue(pidName);
+        pcBuilder.setProperty(
+            new OutputResourceSpecificPropertyBuilder().
+                setResourceSpecificProperty(new SpecificEndpointProperty(DEFAULT_NETWORKMAP)).build());
+        propertiesBuilder.setPropertyContainer(pcBuilder.build()).setPropertyValue(pidNameBuilder.build());
+        THE_SECOND_LIST_PROPERTIES.add(propertiesBuilder.build());
+
+        eppist.add(
+            epBuilder
+                .setSource(THE_FIRST_SOURCE)
+                .setProperties(THE_FIRST_LIST_PROPERTIES)
+                .build());
+        eppist.add(
+            epBuilder
+                .setSource(THE_SECOND_SOURCE)
+                .setProperties(THE_SECOND_LIST_PROPERTIES).build());
+
+        EndpointPropertyMapBuilder endpointPropertyMapBuilder = new EndpointPropertyMapBuilder();
+        endpointPropertyMapBuilder.setEndpointProperty(eppist);
+
+        EndpointPropertymapDataBuilder endpointPropertymapDataBuilder = new EndpointPropertymapDataBuilder();
+        endpointPropertymapDataBuilder.setEndpointPropertyMap(endpointPropertyMapBuilder.build());
+
+        EndpointpropertyResponseBuilder endpointpropertyResponseBuilder = new EndpointpropertyResponseBuilder();
+        endpointpropertyResponseBuilder.setEndpointpropertyData(endpointPropertymapDataBuilder.build());
+
+        QueryOutputBuilder queryOutputBuilder = new QueryOutputBuilder();
+        queryOutputBuilder.setType(ResourceTypeEndpointproperty.class).setResponse(endpointpropertyResponseBuilder.build());
+        when(rpcResult.getResult()).thenReturn(queryOutputBuilder.build());
+        when(future.get()).thenReturn(rpcResult);
+        when(epService.query((QueryInput) anyObject())).thenReturn(future);
+        when(session.getRpcService(AltoModelEndpointpropertyService.class)).thenReturn(epService);
+        when(session.getSALService(DataBroker.class)).thenReturn(new DataBroker() {
+            @Override public ReadOnlyTransaction newReadOnlyTransaction() {
+                return null;
+            }
+
+            @Override public ReadWriteTransaction newReadWriteTransaction() {
+                return null;
+            }
+
+            @Override public WriteTransaction newWriteOnlyTransaction() {
+                return null;
+            }
+
+            @Override public ListenerRegistration<DataChangeListener> registerDataChangeListener(
+                LogicalDatastoreType logicalDatastoreType, InstanceIdentifier<?> instanceIdentifier,
+                DataChangeListener dataChangeListener, DataChangeScope dataChangeScope) {
+                return null;
+            }
+
+            @Override public BindingTransactionChain createTransactionChain(
+                TransactionChainListener transactionChainListener) {
+                return null;
+            }
+
+            @Nonnull @Override
+            public <T extends DataObject, L extends DataTreeChangeListener<T>> ListenerRegistration<L> registerDataTreeChangeListener(
+                @Nonnull DataTreeIdentifier<T> dataTreeIdentifier, @Nonnull L l) {
+                return null;
+            }
+        });
+        doReturn(ctagIID).when(anbreSpy).getResourceByPath(eq(PATH), (ReadOnlyTransaction) anyObject());
+        RFC7285EndpointPropertyMap.Meta meta = new RFC7285EndpointPropertyMap.Meta();
+        RFC7285VersionTag vtag = new RFC7285VersionTag();
+        vtag.rid = DEFAULT_RID;
+        vtag.tag = DEFAULT_TAG;
+        meta.netmap_tags = new LinkedList<>();
+        meta.netmap_tags.add(vtag);
+        doReturn(meta).when(anbreSpy).buildMeta((InstanceIdentifier<?>) anyObject());
+
+        anbreSpy.onSessionInitiated(session);
+        Response response = anbreSpy.getEndpointProperty(PATH, ENDPOINTPROPERTY_FILTER);
+        String stringResponse = response.getEntity().toString();
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode responseNode = mapper.readTree(stringResponse);
+        JsonNode endpointProperties = responseNode.get(FIELD_ENDPOINT_PROPERTIES);
+        JsonNode expectedEndpointProperties = mapper.readTree(TARGET_ENDPOINT_PREOPERTIES);
+
+        assertEquals(expectedEndpointProperties, endpointProperties);
+    }
+}
diff --git a/alto-core/standard-northbound-routes/endpointproperty/pom.xml b/alto-core/standard-northbound-routes/endpointproperty/pom.xml
new file mode 100644 (file)
index 0000000..c84c035
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright Â© 2015 Copyright (c) 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 INTERNAL
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>odlparent</artifactId>
+        <version>1.7.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.alto.core</groupId>
+    <artifactId>routes-endpointproperty-aggregator</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+    <name>alto-northbound-route-endpointproperty-aggregator</name>
+    <packaging>pom</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <prerequisites>
+        <maven>3.1.1</maven>
+    </prerequisites>
+
+    <profiles>
+        <profile>
+            <id>minimal</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <modules>
+                <module>api</module>
+                <module>impl</module>
+            </modules>
+        </profile>
+
+        <profile>
+            <id>alto-dev</id>
+            <modules>
+                <module>api</module>
+                <module>impl</module>
+            </modules>
+        </profile>
+
+        <profile>
+            <id>alto-test</id>
+            <modules>
+                <module>api</module>
+                <module>impl</module>
+            </modules>
+        </profile>
+    </profiles>
+    <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-install-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
index a6510a69d31a6093d61dfc538f61e95bdbefd10e..2321c6ca055ac4d8eac61c34235a14d9ac07c199 100644 (file)
@@ -33,6 +33,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
         <module>networkmap</module>
         <module>costmap</module>
         <module>endpointcost</module>
+        <module>endpointproperty</module>
       </modules>
     </profile>
 
@@ -43,6 +44,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
         <module>networkmap</module>
         <module>costmap</module>
         <module>endpointcost</module>
+        <module>endpointproperty</module>
       </modules>
     </profile>
 
index a374d8443a0aee0e371f4795eeff4981b6421e6c..f81560b86ea6c20c021ee3ed9151d9f968f1097d 100644 (file)
@@ -96,11 +96,11 @@ module alto-model-endpointproperty-rfc7285 {
 
         ext:augment-identifier "rfc7285-endpoint-filter-property";
 
-        case resource-specific-property {
+        case input-resource-specific-property {
             uses resource-specific-property;
         }
 
-        case global-property {
+        case input-global-property {
             uses global-property;
         }
     }
@@ -131,14 +131,14 @@ module alto-model-endpointproperty-rfc7285 {
         }
     }
 
-    augment "/alto-eps:query/alto-eps:output/alto-eps:response/alto-eps:endpointproperty-response/alto-eps:endpointproperty-data/endpoint-propertymap-data/endpoint-property-map/endpoint-property/property/property" {
+    augment "/alto-eps:query/alto-eps:output/alto-eps:response/alto-eps:endpointproperty-response/alto-eps:endpointproperty-data/endpoint-propertymap-data/endpoint-property-map/endpoint-property/properties/property-container/property" {
         ext:augment-identifier "rfc7285-endpoint-propertymap-property";
 
-        case resource-specific-property {
+        case output-resource-specific-property {
             uses resource-specific-property;
         }
 
-        case global-property {
+        case output-global-property {
             uses global-property;
         }
     }
@@ -151,11 +151,13 @@ module alto-model-endpointproperty-rfc7285 {
                     uses "typed-address-data";
                 }
 
-                container "property" {
-                    uses "typed-property-data";
-                }
+                list "properties" {
+                    container "property-container" {
+                        uses "typed-property-data";
+                    }
 
-                choice "property-value" {
+                    choice "property-value" {
+                    }
                 }
             }
         }
@@ -175,7 +177,7 @@ module alto-model-endpointproperty-rfc7285 {
 
 
 
-    augment "/alto-eps:query/alto-eps:output/alto-eps:response/alto-eps:endpointproperty-response/alto-eps:endpointproperty-data/endpoint-propertymap-data/endpoint-property-map/endpoint-property/property-value"{
+    augment "/alto-eps:query/alto-eps:output/alto-eps:response/alto-eps:endpointproperty-response/alto-eps:endpointproperty-data/endpoint-propertymap-data/endpoint-property-map/endpoint-property/properties/property-value"{
         case pid-name {
             leaf "value"{
                 type base:pid-name;
index 327468b1b8e86ac995b5e14fee3191a9076c3ad0..153e4d5c7bfe8382581510671d470bf8bdc7fc63 100644 (file)
@@ -119,5 +119,56 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>alto-service-model-base-api</artifactId>
       <version>${project.version}</version>
     </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.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-service-model-ird-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.basic</groupId>
+      <artifactId>alto-simple-ird-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
   </dependencies>
 </project>
index c9bf1ac597503ad2556050561b0d879167f2a2f9..099492614f6e7cf0eb51bb18e68f6b123b8381cf 100644 (file)
@@ -16,18 +16,21 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.alto.core/alto-service-model-base-features/${project.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.alto.core/alto-service-model-networkmap-features/${project.version}/xml/features</repository>
 
   <feature name='odl-alto-service-model-endpointproperty-api' version='${project.version}' description='OpenDaylight :: alto-service-model-endpointproperty :: api'>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
     <feature version='${project.version}'>odl-alto-service-model-base</feature>
-    <feature version='${project.version}'>odl-alto-service-model-networkmap-api</feature>
     <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-api/${project.version}</bundle>
   </feature>
 
   <feature name='odl-alto-service-model-endpointproperty' version='${project.version}' description='OpenDaylight :: alto-service-model-endpointproperty'>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
     <feature version='${project.version}'>odl-alto-service-model-endpointproperty-api</feature>
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-northbound.xml">
+      mvn:org.opendaylight.alto.core/alto-northbound-impl/${project.version}/xml/config
+    </configfile>
     <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-impl/${project.version}</bundle>
     <configfile finalname="${configfile.directory}/alto-service-model-endpointproperty.xml">mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-impl/${project.version}/xml/config</configfile>
   </feature>
@@ -44,4 +47,64 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version="${dlux.version}">odl-dlux-yangui</feature>
   </feature>
 
+  <feature name='odl-alto-standard-types' version='${project.version}'
+           description='OpenDaylight :: alto :: standard-types'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <bundle>mvn:org.opendaylight.alto.core/alto-basic-types/${project.version}</bundle>
+  </feature>
+<!--
+  <feature name='odl-alto-standard-service-models-test' version='${project.version}'
+           description='OpenDaylight :: alto :: standard-service-model'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+
+    <feature version='${project.version}'>odl-alto-standard-types</feature>
+    <feature version='${project.version}'>odl-alto-resourcepool</feature>
+
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-service-model-endpointproperty.xml">
+      mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-impl/${project.version}/xml/config
+    </configfile>
+  </feature>
+-->
+  <feature name='odl-alto-standard-northbound-route-endpointproperty' version='${project.version}'
+           description='OpenDaylight :: alto :: standard-northbound-route'>
+    <!-- TODO standard routes for network map/cost map/endpoint cost/endpoint property -->
+    <feature version='${project.version}'>odl-alto-standard-service-models</feature>
+    <feature version='${project.version}'>odl-alto-northbound</feature>
+
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-northbound-route-endpointproperty.xml">
+      mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-impl/${project.version}/xml/config
+    </configfile>
+  </feature>
+
+  <feature name='odl-alto-northbound' version='${project.version}'
+           description='OpenDaylight :: alto :: northbound'>
+    <feature version="${restconf.version}">odl-restconf</feature>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-northbound.xml">
+      mvn:org.opendaylight.alto.core/alto-northbound-impl/${project.version}/xml/config
+    </configfile>
+  </feature>
+
+  <feature name='odl-alto-standard-service-models' version='${project.version}'
+           description='OpenDaylight :: alto :: standard-service-model'>
+    <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
+    <feature version='${project.version}'>odl-alto-standard-types</feature>
+    <feature version='${project.version}'>odl-alto-resourcepool</feature>
+
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-base-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-ird-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-networkmap-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointcost-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-costmap-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-service-model-endpointproperty-api/${project.version}</bundle>
+  </feature>
+
 </features>
index 63792a655dcd05dc770537635358f119e9a8b8cb..a53ec50829a550750f1bdbe6e9cf504552e1f8f5 100644 (file)
@@ -46,6 +46,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <version>${project.version}</version>
     </dependency>
 
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>alto-northbound-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
     <!-- Testing Dependencies -->
     <dependency>
       <groupId>junit</groupId>
index 5a0e7c72cf1405ddb3a52a2fca6095ae1119d941..611539f3bbf3ba1e71bcc74fc02e78fb57447a10 100644 (file)
@@ -13,6 +13,8 @@ import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+import org.opendaylight.alto.core.northbound.api.exception.AltoBadFormatException;
+import org.opendaylight.alto.core.northbound.api.exception.AltoErrorTestException;
 import org.opendaylight.alto.core.resourcepool.ResourcepoolUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
@@ -23,13 +25,10 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-
-
-
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.resourcepool.rev150921.context.Resource;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.PidName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.ResourceId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.core.types.rev150921.SpecificEndpointProperty;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.AltoModelEndpointpropertyService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.QueryOutput;
@@ -39,18 +38,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpoint
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.alto.response.endpointproperty.response.EndpointpropertyResponseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rev151021.endpointproperty.request.data.EndpointpropertyParams;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.TypedAddressData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.TypedPropertyData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointproperty.filter.data.endpointproperty.filter.PropertyFilter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.EndpointPropertyMapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.EndpointProperty;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.EndpointPropertyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.PropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.Properties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.PropertiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.endpointpropertymap.response.data.endpoint.property.map.endpoint.property.properties.PropertyContainerBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.EndpointpropertyFilterData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.input.request.endpointproperty.request.endpointproperty.params.filter.endpointproperty.filter.data.endpointproperty.filter.property.filter.property.InputGlobalProperty;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.EndpointPropertymapDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.property.value.PidNameBuilder;
-
-
-
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.container.property.OutputResourceSpecificPropertyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.alto.service.model.endpointproperty.rfc7285.rev151021.query.output.response.endpointproperty.response.endpointproperty.data.endpoint.propertymap.data.endpoint.property.map.endpoint.property.properties.property.value.PidNameBuilder;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -71,8 +71,6 @@ public class AltoEndpointPropertyProvider implements BindingAwareProvider, AutoC
     private static final ResourceId TEST_ENDPOINTPROPERTY_RID = new ResourceId(TEST_ENDPOINTPROPERTY_NAME);
     private InstanceIdentifier<Resource> m_testIID = null;
 
-
-
     protected void createContextTag()
             throws InterruptedException, ExecutionException, TransactionCommitFailedException {
         WriteTransaction wx = m_dataBroker.newWriteOnlyTransaction();
@@ -136,48 +134,63 @@ public class AltoEndpointPropertyProvider implements BindingAwareProvider, AutoC
         }
     }
 
-
-
-
-
-
-
-
-
     @Override
     public Future<RpcResult<QueryOutput>> query(QueryInput input) {
-
-
+        LOG.info("test-model-endpointproperty has been called");
         if (!input.getType().equals(ResourceTypeEndpointproperty.class)) {
             return RpcResultBuilder.<QueryOutput>failed().buildFuture();
         }
 
         EndpointpropertyRequest request = (EndpointpropertyRequest)input.getRequest();
-
         EndpointpropertyParams params = request.getEndpointpropertyParams();
-
-
         EndpointpropertyFilterData filter= (EndpointpropertyFilterData)params.getFilter();
 
-
-
-
         List<? extends TypedAddressData> endpoints=filter.getEndpointpropertyFilter().getEndpointFilter();
-        List<? extends TypedPropertyData> properties = filter.getEndpointpropertyFilter().getPropertyFilter();
-
+        List<PropertyFilter> properties = filter.getEndpointpropertyFilter().getPropertyFilter();
+
+        for (PropertyFilter property: properties) {
+            if (property.getProperty() instanceof InputGlobalProperty) {
+                String propertyString = ((InputGlobalProperty)property.getProperty()).getGlobalProperty().getValue();
+                if (propertyString.equals("no-such-property")) {
+                    throw new AltoBadFormatException(AltoErrorTestException.ERROR_CODES.E_INVALID_FIELD_VALUE.name(), "properties", "no-such-property");
+                }
+            }
+        }
 
         int order = 0;
         LinkedList<EndpointProperty> eppist = new LinkedList<EndpointProperty>();
         for (TypedAddressData endpoint: endpoints) {
-            for (TypedPropertyData property: properties) {
+            SourceBuilder srcBuilder = new SourceBuilder();
+            srcBuilder.setAddress(endpoint.getAddress());
+
+            PidName pidName = new PidName("PID1");
+            PidNameBuilder pidNameBuilder = new PidNameBuilder();
+            pidNameBuilder.setValue(pidName);
+
+            EndpointPropertyBuilder epBuilder = new EndpointPropertyBuilder();
+            epBuilder.setSource(srcBuilder.build());
+
+            LinkedList<Properties> propertiesInResponse = new LinkedList<Properties>();
+            PropertiesBuilder propertiesBuilder = new PropertiesBuilder();
+            PropertyContainerBuilder pcBuilder = new PropertyContainerBuilder();
+            pcBuilder.setProperty(
+                    new OutputResourceSpecificPropertyBuilder().
+                            setResourceSpecificProperty(new SpecificEndpointProperty("my-default-networkmap.pid")).build());
+            propertiesBuilder.setPropertyContainer(pcBuilder.build()).setPropertyValue(pidNameBuilder.build());
+            propertiesInResponse.add(propertiesBuilder.build());
+            epBuilder.setProperties(propertiesInResponse);
+            //propertiesBuilder.setPropertyContainer(new PropertyContainerBuilder().build()).setPropertyValue(pidName);
 
 
-                SourceBuilder srcBuilder = new SourceBuilder();
-                srcBuilder.setAddress(endpoint.getAddress());
+            /*for (TypedPropertyData property: properties) {
 
 
-                PropertyBuilder propertyBuilder = new PropertyBuilder();
-                propertyBuilder.setProperty(property.getProperty());
+            //    SourceBuilder srcBuilder = new SourceBuilder();
+            //    srcBuilder.setAddress(endpoint.getAddress());
+
+
+            //    PropertyContainerBuilder propertyBuilder = new PropertyContainerBuilder();
+            //    propertyBuilder.setProperty(property.getProperty());
 
                 PidName pidName = new PidName("PID1");
                 PidNameBuilder pidNameBuilder = new PidNameBuilder();
@@ -187,18 +200,19 @@ public class AltoEndpointPropertyProvider implements BindingAwareProvider, AutoC
 
                 EndpointPropertyBuilder epBuilder = new EndpointPropertyBuilder();
                 epBuilder.setSource(srcBuilder.build());
-                epBuilder.setProperty(propertyBuilder.build());
+                epBuilder.setProperties()
+                        setProperty(propertyBuilder.build());
                 epBuilder.setPropertyValue(pidNameBuilder.build());
 
 
                 eppist.add(epBuilder.build());
-            }
+            }*/
+            eppist.add(epBuilder.build());
         }
 
         EndpointPropertyMapBuilder endpointPropertyMapBuilder = new EndpointPropertyMapBuilder();
         endpointPropertyMapBuilder.setEndpointProperty(eppist);
 
-
         EndpointPropertymapDataBuilder endpointPropertymapDataBuilder = new EndpointPropertymapDataBuilder();
         endpointPropertymapDataBuilder.setEndpointPropertyMap(endpointPropertyMapBuilder.build());
 
@@ -206,8 +220,8 @@ public class AltoEndpointPropertyProvider implements BindingAwareProvider, AutoC
         endpointpropertyResponseBuilder.setEndpointpropertyData(endpointPropertymapDataBuilder.build());
 
         QueryOutputBuilder queryOutputBuilder = new QueryOutputBuilder();
-        queryOutputBuilder.setResponse(endpointpropertyResponseBuilder.build());
-        return RpcResultBuilder.<QueryOutput>success(queryOutputBuilder.build()).buildFuture();
+        queryOutputBuilder.setType(ResourceTypeEndpointproperty.class).setResponse(endpointpropertyResponseBuilder.build());
+        return RpcResultBuilder.success(queryOutputBuilder.build()).buildFuture();
     }
 
 }
index 7dcb8ac9505eb50cd20b880d153efa0ba20e2aa7..6b6fc29b5130a2702ec6f7d4b7b6b6b3d55f3088 100644 (file)
@@ -207,6 +207,26 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <classifier>config</classifier>
     </dependency>
 
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.alto.core</groupId>
+      <artifactId>alto-northbound-route-endpointproperty-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+
     <dependency>
       <groupId>org.opendaylight.alto.core</groupId>
       <artifactId>alto-service-model-ird-api</artifactId>
index 99dedc16b257f681cc68a07459e1897799ae18b6..c2c17d18c4213a4915a3949416787cf52d8d95bd 100644 (file)
@@ -171,6 +171,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <configfile finalname="${configfile.directory}/alto-northbound-route-endpointcost.xml">
       mvn:org.opendaylight.alto.core/alto-northbound-route-endpointcost-impl/${project.version}/xml/config
     </configfile>
+
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/alto-northbound-route-endpointproperty.xml">
+      mvn:org.opendaylight.alto.core/alto-northbound-route-endpointproperty-impl/${project.version}/xml/config
+    </configfile>
   </feature>
 
   <feature name='odl-alto-standard-resource-translator' version='${project.version}'
diff --git a/test/scripts/endpointpropertymap/endpointpropertymap_input b/test/scripts/endpointpropertymap/endpointpropertymap_input
new file mode 100644 (file)
index 0000000..4853539
--- /dev/null
@@ -0,0 +1,17 @@
+{
+    "input": {
+        "endpointproperty-params": {
+          "endpointproperty-filter": {
+            "property-filter": [
+              {"resource-specific-property": "my-default-networkmap.pid"}
+            ],
+            "endpoint-filter": [
+              {"ipv4":"192.0.2.34"},
+              {"ipv4":"203.0.113.129"}
+            ]
+          }
+        },
+        "service-reference": "/alto-resourcepool:context[alto-resourcepool:context-id='00000000-0000-0000-0000-000000000000']/alto-resourcepool:resource[alto-resourcepool:resource-id='test-model-endpointproperty']/alto-resourcepool:context-tag[alto-resourcepool:tag='1b2fc6780d7c42979cdcf75df0da1336']",
+        "type": "alto-model-endpointproperty:resource-type-endpointproperty"
+    }
+}
diff --git a/test/scripts/northbound/nbr-endpointproperty-create b/test/scripts/northbound/nbr-endpointproperty-create
new file mode 100755 (executable)
index 0000000..d36d7c1
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+ENDPOINTPROPERTY_PATH=$1
+RESOURCE_ID=$2
+if [ $3 ]; then
+       CONTEXT_ID=$3
+else
+       CONTEXT_ID="00000000-0000-0000-0000-000000000000"
+fi
+
+DATA=$(cat ./template/nbr-record-endpointproperty \
+               | sed 's/\$1/'$ENDPOINTPROPERTY_PATH'/g' \
+               | sed 's/\$2/'$CONTEXT_ID'/g' \
+               | sed 's/\$3/'$RESOURCE_ID'/g')
+
+# echo $DATA | python -m json.tool
+
+curl -X PUT -u admin:admin -H "Content-Type: application/json" \
+       -d "$DATA" \
+       http://localhost:8181/restconf/config/alto-nbr-endpointproperty:records/record/$ENDPOINTPROPERTY_PATH
diff --git a/test/scripts/northbound/query-nbr-endpointproperty b/test/scripts/northbound/query-nbr-endpointproperty
new file mode 100755 (executable)
index 0000000..b248ac8
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+ENDPOINTPROPERTY_PATH=$1
+
+DATA=$(cat ./template/endpointproperty-filter)
+
+
+
+curl -X POST -u admin:admin -H "Content-Type: application/alto-endpointpropparams+json" -H "Accept: application/alto-endpointprop+json"\
+       -d "$DATA" -v \
+       http://localhost:8080/alto/endpointproperty/$ENDPOINTPROPERTY_PATH #lo| python -m json.tool
diff --git a/test/scripts/northbound/template/endpointproperty-filter b/test/scripts/northbound/template/endpointproperty-filter
new file mode 100644 (file)
index 0000000..fd2bec1
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "properties" : [ "my-default-networkmap.pid",
+                   "priv:ietf-example-prop" ],
+  "endpoints"  : [ "ipv4:192.0.2.34",
+                   "ipv4:203.0.113.129" ]
+}
diff --git a/test/scripts/northbound/template/nbr-record-endpointproperty b/test/scripts/northbound/template/nbr-record-endpointproperty
new file mode 100644 (file)
index 0000000..0ff0305
--- /dev/null
@@ -0,0 +1,6 @@
+{
+       "record": {
+               "path": "$1",
+               "resource-iid": "/alto-resourcepool:context[alto-resourcepool:context-id='$2']/alto-resourcepool:resource[alto-resourcepool:resource-id='$3']"
+       }
+}