From 1ba64a4a45f26e8bdb58e866e540aa58f32e2e52 Mon Sep 17 00:00:00 2001 From: Ofir Sonsino Date: Wed, 20 Sep 2017 14:08:19 +0300 Subject: Change management and PNF support Issue-ID: VID-44, VID-48, VID-49, VID-50, VID-51, VID-52 Change-Id: I83e940aad2e4e294a0927b546c4c08ca8e539a65 Signed-off-by: Ofir Sonsino --- epsdk-app-onap/.classpath | 6 - .../src/main/webapp/WEB-INF/conf/system.properties | 7 +- .../src/main/webapp/WEB-INF/jsp/serviceModels.jsp | 18 +- .../src/main/webapp/WEB-INF/jsp/welcome.jsp | 2 +- .../app/fusion/external/ebz/angular_js/app.js | 5 +- .../app/fusion/external/ebz/angular_js/appDS2.js | 3 +- .../angular-bootstrap-multiselect.min.js | 1 + .../org/openecomp/aai/util/AAIRestInterface.java | 48 + .../src/main/java/org/openecomp/vid/RelatedTo.java | 36 + .../main/java/org/openecomp/vid/aai/AaiClient.java | 514 +++--- .../org/openecomp/vid/aai/AaiClientInterface.java | 11 + .../org/openecomp/vid/aai/AaiGetVnfResponse.java | 28 + .../org/openecomp/vid/aai/ServiceProperties.java | 90 + .../main/java/org/openecomp/vid/aai/VnfResult.java | 44 + .../openecomp/vid/aai/model/RelatedToProperty.java | 34 + .../org/openecomp/vid/aai/model/Relationship.java | 55 + .../openecomp/vid/aai/model/RelationshipData.java | 29 + .../openecomp/vid/aai/model/RelationshipList.java | 24 + .../vid/aai/model/ServiceRelationships.java | 90 + .../vid/asdc/beans/tosca/ToscaMetadata.java | 30 - .../vid/asdc/parser/ToscaParserImpl2.java | 2 + .../changeManagement/ChangeManagementRequest.java | 63 + .../changeManagement/ChangeManagementResponse.java | 19 + .../vid/changeManagement/CloudConfiguration.java | 55 + .../openecomp/vid/changeManagement/CmResponse.java | 17 + .../changeManagement/LeanCloudConfiguration.java | 20 + .../openecomp/vid/changeManagement/ModelInfo.java | 138 ++ .../ModelInfoOfRelatedInstance.java | 122 ++ .../vid/changeManagement/MsoRequestDetails.java | 31 + .../vid/changeManagement/RelatedInstance.java | 29 + .../vid/changeManagement/RelatedInstanceList.java | 23 + .../vid/changeManagement/RequestDetails.java | 56 + .../changeManagement/RequestDetailsWrapper.java | 9 + .../vid/changeManagement/RequestInfo.java | 69 + .../vid/changeManagement/RequestParameters.java | 44 + .../vid/changeManagement/UpdateRequestInfo.java | 26 + .../openecomp/vid/controller/AaiController.java | 1728 ++++++++++---------- .../vid/controller/ChangeManagementController.java | 71 + .../org/openecomp/vid/controller/MsoConfig.java | 29 + .../openecomp/vid/controller/MsoController.java | 528 +++--- .../openecomp/vid/controller/PolicyController.java | 90 + .../vid/controller/SchedulerController.java | 244 +++ .../openecomp/vid/controller/VidController.java | 1 + .../openecomp/vid/factories/MsoRequestFactory.java | 15 + .../org/openecomp/vid/model/CommandProperty.java | 12 +- .../vid/model/VersionByInvariantIdsRequest.java | 11 + .../java/org/openecomp/vid/model/VolumeGroup.java | 2 +- .../java/org/openecomp/vid/model/Workflow.java | 47 + .../org/openecomp/vid/mso/MsoBusinessLogic.java | 415 +++++ .../org/openecomp/vid/mso/MsoClientFactory.java | 37 + .../java/org/openecomp/vid/mso/MsoInterface.java | 75 + .../java/org/openecomp/vid/mso/MsoLocalClient.java | 85 + .../org/openecomp/vid/mso/MsoLocalClientNew.java | 216 +++ .../java/org/openecomp/vid/mso/MsoProperties.java | 21 +- .../org/openecomp/vid/mso/MsoRestInterface.java | 73 +- .../openecomp/vid/mso/MsoRestInterfaceFactory.java | 32 +- .../org/openecomp/vid/mso/MsoRestInterfaceIfc.java | 15 +- .../openecomp/vid/mso/RestMsoImplementation.java | 326 ++++ .../vid/mso/rest/MsoBusinessLogicNew.java | 67 + .../openecomp/vid/mso/rest/MsoRestClientNew.java | 333 ++++ .../org/openecomp/vid/mso/rest/RelatedModel.java | 4 + .../org/openecomp/vid/mso/rest/RequestDetails.java | 25 +- .../org/openecomp/vid/mso/rest/RequestList.java | 6 +- .../org/openecomp/vid/mso/rest/RequestWrapper.java | 35 + .../java/org/openecomp/vid/mso/rest/Response.java | 54 + .../org/openecomp/vid/mso/rest/RestInterface.java | 81 + .../main/java/org/openecomp/vid/mso/rest/Task.java | 119 ++ .../java/org/openecomp/vid/mso/rest/TaskList.java | 16 + .../org/openecomp/vid/policy/PolicyProperties.java | 26 + .../vid/policy/PolicyResponseWrapper.java | 56 + .../org/openecomp/vid/policy/PolicyRestInt.java | 67 + .../openecomp/vid/policy/PolicyRestInterface.java | 234 +++ .../vid/policy/PolicyRestInterfaceFactory.java | 14 + .../vid/policy/PolicyRestInterfaceIfc.java | 58 + .../java/org/openecomp/vid/policy/PolicyUtil.java | 71 + .../java/org/openecomp/vid/policy/RestObject.java | 68 + .../openecomp/vid/policy/rest/RequestDetails.java | 107 ++ .../vid/properties/MsoClientConfiguration.java | 9 + .../main/java/org/openecomp/vid/roles/Role.java | 2 +- .../org/openecomp/vid/scheduler/RestObject.java | 44 + .../RestObjects/GetTimeSlotsRestObject.java | 11 + .../RestObjects/PostCreateNewVnfRestObject.java | 10 + .../RestObjects/PostSubmitVnfChangeRestObject.java | 10 + .../vid/scheduler/RestObjects/RestObject.java | 39 + .../vid/scheduler/SchedulerProperties.java | 24 + .../vid/scheduler/SchedulerResponseWrapper.java | 71 + .../GetTimeSlotsWrapper.java | 5 + .../PostCreateNewVnfWrapper.java | 39 + .../PostSubmitVnfChangeTimeSlotsWrapper.java | 38 + .../SchedulerResponseWrapper.java | 57 + .../openecomp/vid/scheduler/SchedulerRestInt.java | 42 + .../vid/scheduler/SchedulerRestInterface.java | 208 +++ .../scheduler/SchedulerRestInterfaceFactory.java | 15 + .../vid/scheduler/SchedulerRestInterfaceIfc.java | 21 + .../org/openecomp/vid/scheduler/SchedulerUtil.java | 100 ++ .../vid/scheduler/rest/RequestDetails.java | 106 ++ .../org/openecomp/vid/services/AaiService.java | 9 + .../org/openecomp/vid/services/AaiServiceImpl.java | 35 +- .../vid/services/ChangeManagementService.java | 14 + .../vid/services/ChangeManagementServiceImpl.java | 109 ++ .../openecomp/vid/services/WorkflowService.java | 9 + .../vid/services/WorkflowServiceImpl.java | 40 + .../src/main/resources/json/mso/modelInfo | 13 +- vid-app-common/src/main/resources/json/mso/request | 10 +- .../src/main/resources/json/mso/requestInfo | 8 + .../src/main/resources/json/mso/requestStatus | 10 +- .../main/resources/mso_complete_manual_task.json | 5 + .../resources/mso_create_instance_response.json | 6 + .../mso_get_manual_task_by_request_id.json | 23 + .../resources/mso_get_orchestration_requests.json | 88 + .../vid/external/bootstrap/css/bootstrap.min.css | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 ++++ .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../app/vid/external/bootstrap/js/bootstrap.min.js | 7 + .../webapp/app/vid/external/lodash/lodash.min.js | 136 ++ .../angular-bootstrap-multiselect.min.js | 1 + .../src/main/webapp/app/vid/images/Calendar.svg | 39 + .../main/webapp/app/vid/images/Calendar_blue.svg | 45 + .../vid/scripts/constants/componentConstants.js | 26 +- .../app/vid/scripts/constants/fieldConstants.js | 153 +- .../app/vid/scripts/constants/vidConfiguration.js | 10 +- .../scripts/controller/InstantiationController.js | 3 - .../scripts/controller/ServiceModelController.js | 4 +- .../webapp/app/vid/scripts/controller/VidApp.js | 5 + .../scripts/controller/aaiSubscriberController.js | 15 +- .../controller/change-management.controller.js | 138 ++ .../directives/angularjs-datetime-picker.js | 361 ++++ .../change-managements-by-statuses.filter.js | 22 + .../webapp/app/vid/scripts/filters/date.filter.js | 18 + .../alert-change-management.css | 3 + .../alert-change-management.html | 12 + .../alert-new-scheduler.controller.js | 33 + .../alert-new-scheduler/alert-new-scheduler.css | 3 + .../alert-new-scheduler/alert-new-scheduler.html | 12 + .../change-management-manual-tasks.controller.js | 56 + .../change-management-manual-tasks.html | 7 + .../failed-change-management.css | 3 + .../failed-change-management.html | 12 + .../in-progress-change-management.css | 3 + .../in-progress-change-management.html | 12 + .../new-change-management.controller.js | 369 +++++ .../new-change-management.css | 130 ++ .../new-change-management.html | 68 + .../new-scheduler/new-scheduler.controller.js | 455 ++++++ .../scripts/modals/new-scheduler/new-scheduler.css | 145 ++ .../modals/new-scheduler/new-scheduler.html | 101 ++ .../pending-change-management.css | 7 + .../pending-change-management.html | 12 + .../webapp/app/vid/scripts/services/aaiService.js | 296 ++-- .../scripts/services/change-management.service.js | 76 + .../app/vid/scripts/services/creationService.js | 4 +- .../webapp/app/vid/scripts/services/msoService.js | 376 +++-- .../app/vid/scripts/services/schedulerService.js | 104 ++ .../vid/scripts/view-models/change-management.html | 112 ++ .../app/vid/scripts/view-models/instantiate.htm | 3 + .../app/vid/styles/angularjs-datetime-picker.css | 76 + .../app/vid/styles/change-management-icons.css | 82 + .../webapp/app/vid/styles/change-management.css | 157 ++ .../src/main/webapp/app/vid/styles/common.css | 3 + .../main/webapp/app/vid/styles/fonts/icomoon.eot | Bin 0 -> 5200 bytes .../main/webapp/app/vid/styles/fonts/icomoon.svg | 23 + .../main/webapp/app/vid/styles/fonts/icomoon.ttf | Bin 0 -> 5036 bytes .../main/webapp/app/vid/styles/fonts/icomoon.woff | Bin 0 -> 5112 bytes .../opencomp/vid/controller/MsoControllerTest.java | 112 ++ .../opencomp/vid/controller/VidControllerTest.java | 16 + .../vid/services/ChangeManagementServiceTest.java | 29 + .../test/resources/WEB-INF/conf/system.properties | 24 +- .../test/resources/WEB-INF/jsp/serviceModels.jsp | 10 + .../src/test/resources/WEB-INF/jsp/welcome.jsp | 5 +- vid-app-common/src/test/resources/mso.properties | 16 + vid-app-common/src/test/resources/msoRequest.json | 25 + 174 files changed, 11020 insertions(+), 1791 deletions(-) create mode 100644 epsdk-app-onap/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/RelatedTo.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/AaiGetVnfResponse.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/ServiceProperties.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/VnfResult.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelatedToProperty.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/model/Relationship.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipData.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipList.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/aai/model/ServiceRelationships.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementRequest.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementResponse.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CloudConfiguration.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CmResponse.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/LeanCloudConfiguration.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfo.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfoOfRelatedInstance.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/MsoRequestDetails.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstance.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstanceList.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetails.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetailsWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestInfo.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestParameters.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/changeManagement/UpdateRequestInfo.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/controller/ChangeManagementController.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/controller/MsoConfig.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/controller/PolicyController.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/controller/SchedulerController.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/factories/MsoRequestFactory.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/model/VersionByInvariantIdsRequest.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/model/Workflow.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/MsoBusinessLogic.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/MsoClientFactory.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/MsoInterface.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClient.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClientNew.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/RestMsoImplementation.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoBusinessLogicNew.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoRestClientNew.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Response.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RestInterface.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Task.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/mso/rest/TaskList.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyProperties.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyResponseWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInt.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterface.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceFactory.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceIfc.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyUtil.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/RestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/policy/rest/RequestDetails.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/properties/MsoClientConfiguration.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/GetTimeSlotsRestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostCreateNewVnfRestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostSubmitVnfChangeRestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/RestObject.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerProperties.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/GetTimeSlotsWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostCreateNewVnfWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostSubmitVnfChangeTimeSlotsWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/SchedulerResponseWrapper.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInt.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterface.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceFactory.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceIfc.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerUtil.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/scheduler/rest/RequestDetails.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementService.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementServiceImpl.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowService.java create mode 100644 vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowServiceImpl.java create mode 100644 vid-app-common/src/main/resources/mso_complete_manual_task.json create mode 100644 vid-app-common/src/main/resources/mso_create_instance_response.json create mode 100644 vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json create mode 100644 vid-app-common/src/main/resources/mso_get_orchestration_requests.json create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/css/bootstrap.min.css create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 vid-app-common/src/main/webapp/app/vid/external/bootstrap/js/bootstrap.min.js create mode 100644 vid-app-common/src/main/webapp/app/vid/external/lodash/lodash.min.js create mode 100644 vid-app-common/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js create mode 100644 vid-app-common/src/main/webapp/app/vid/images/Calendar.svg create mode 100644 vid-app-common/src/main/webapp/app/vid/images/Calendar_blue.svg create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/controller/change-management.controller.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/directives/angularjs-datetime-picker.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/filters/change-managements-by-statuses.filter.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/filters/date.filter.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.controller.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.controller.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.controller.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/services/change-management.service.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/services/schedulerService.js create mode 100644 vid-app-common/src/main/webapp/app/vid/scripts/view-models/change-management.html create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/angularjs-datetime-picker.css create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/change-management-icons.css create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/change-management.css create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/common.css create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.eot create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.svg create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.ttf create mode 100644 vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.woff create mode 100644 vid-app-common/src/test/java/org/opencomp/vid/controller/MsoControllerTest.java create mode 100644 vid-app-common/src/test/java/org/openecomp/vid/services/ChangeManagementServiceTest.java create mode 100644 vid-app-common/src/test/resources/mso.properties create mode 100644 vid-app-common/src/test/resources/msoRequest.json diff --git a/epsdk-app-onap/.classpath b/epsdk-app-onap/.classpath index ede37b2b3..f210876be 100755 --- a/epsdk-app-onap/.classpath +++ b/epsdk-app-onap/.classpath @@ -11,12 +11,6 @@ - - - - - - diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties index e7623665d..0cbc3126a 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties @@ -165,10 +165,15 @@ mso.restapi.vf.module.instance=/serviceInstances/v4//vnfs/< mso.restapi.volume.group.instance=/serviceInstances/v4//vnfs//volumeGroups mso.restapi.get.orc.req=/orchestrationRequests/v4 mso.restapi.get.orc.reqs=/orchestrationRequests/v4? +mso.restapi.get.man.tasks=/tasks/v1 vid.truststore.filename=/opt/app/vid/etc/vid_keystore.jks mso.dme2.client.timeout=30000 mso.dme2.client.read.timeout=120000 vid.truststore.filename=vid_keystore.jks vid.truststore.passwd.x=OBF:1wgg1wfq1uus1uui1x131x0r1x1v1x1j1uvo1uve1wg81wfi +scheduler.create.new.vnf.change.instance=/v1/ChangeManagement/schedules/ +scheduler.get.time.slots=/v1/ChangeManagement/schedules/ +scheduler.server.url=http://BYO.scheduler:8989/scheduler - +scheduler.submit.new.vnf.change=/v1/ChangeManagement/schedules/{scheduleId}/approvals +scheduler.get.schedules=/v1/ChangeManagement/schedules/scheduleDetails/ \ No newline at end of file diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/serviceModels.jsp b/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/serviceModels.jsp index 6d2305108..d0c36d47a 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/serviceModels.jsp +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/serviceModels.jsp @@ -6,6 +6,9 @@ + + + - + + + + + + + @@ -35,11 +44,17 @@ + + + + + + @@ -51,6 +66,7 @@ + <%@ page import="org.openecomp.vid.mso.*"%> <%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%> diff --git a/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/welcome.jsp b/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/welcome.jsp index 9cb6f85b7..ad5331d98 100755 --- a/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/welcome.jsp +++ b/epsdk-app-onap/src/main/webapp/WEB-INF/jsp/welcome.jsp @@ -1,4 +1,4 @@ - +

ONAP


diff --git a/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/app.js b/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/app.js index 0787015bf..59e27470f 100755 --- a/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/app.js +++ b/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/app.js @@ -1,6 +1,5 @@ angular.module('att.abs.helper', []); angular.module('quantum', []); -angular.module('ui.bootstrap', []); -var app=angular.module("abs", ["att.abs", "att.abs.helper","modalServices", - "att.gridster","checklist-model","ngRoute", "ui.bootstrap","ngCookies"]); +var app=angular.module("abs", ["att.abs", "att.abs.helper","modalServices", /*'ngAnimate','ngTouch',*/ 'ui.bootstrap', + "att.gridster","checklist-model","ngRoute", "ngCookies", 'btorfs.multiselect']); diff --git a/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/appDS2.js b/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/appDS2.js index 3a101934c..d982b7855 100755 --- a/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/appDS2.js +++ b/epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/appDS2.js @@ -1,5 +1,4 @@ angular.module('att.abs.helper', []); angular.module('quantum', []); -angular.module('ui.bootstrap', []); -var appDS2=angular.module("abs", ["ngRoute", 'ngMessages', 'ngCookies', 'b2b.att.tpls', 'ddh.att.tpls', 'ddh.att.switches', 'b2b.att.footer', 'b2b.att.header']); +var appDS2=angular.module("abs", ["ngRoute", /*'ngAnimate', 'ngTouch',*/ 'ui.bootstrap', 'ngMessages', 'ngCookies', 'b2b.att.tpls', 'ddh.att.tpls', 'ddh.att.switches', 'b2b.att.footer', 'b2b.att.header', 'btorfs.multiselect']); var app = appDS2; diff --git a/epsdk-app-onap/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js b/epsdk-app-onap/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js new file mode 100644 index 000000000..b9be2c7e4 --- /dev/null +++ b/epsdk-app-onap/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js @@ -0,0 +1 @@ +!function(){"use strict";var a=angular.module("btorfs.multiselect",["btorfs.multiselect.templates"]);a.getRecursiveProperty=function(a,b){return b.split(".").reduce(function(a,b){return a?a[b]:null},a)},a.directive("multiselect",["$filter","$document","$log",function(b,c,d){return{restrict:"AE",scope:{options:"=",displayProp:"@",idProp:"@",searchLimit:"=?",selectionLimit:"=?",showSelectAll:"=?",showUnselectAll:"=?",showSearch:"=?",searchFilter:"=?",disabled:"=?ngDisabled",labels:"=?",showTooltip:"=?",placeholder:"@?"},require:"ngModel",templateUrl:"multiselect.html",link:function(b,e,f,g){b.selectionLimit=b.selectionLimit||0,b.searchLimit=b.searchLimit||25,b.searchFilter="",b.resolvedOptions=[],"function"!=typeof b.options&&(b.resolvedOptions=b.options),"undefined"!=typeof f.disabled&&(b.disabled=!0);var h=function(a){e[0].contains(a.target)||b.$apply(function(){b.open=!1})};c.on("click",h);var i=function(){g.$viewValue?(b.selectedOptions=b.resolvedOptions.filter(function(a){for(var c=b.getId(a),d=0;d1){var a=angular.isDefined(b.selectedOptions)?b.selectedOptions.length:0;return 0===a?b.labels&&b.labels.select?b.labels.select:b.placeholder||"Select":a+" "+(b.labels&&b.labels.itemsSelected?b.labels.itemsSelected:"selected")}return b.labels&&b.labels.select?b.labels.select:b.placeholder||"Select"},b.selectAll=function(){b.selectedOptions=b.resolvedOptions.slice(),b.unselectedOptions=[]},b.unselectAll=function(){b.selectedOptions=[],b.unselectedOptions=b.resolvedOptions.slice()},b.toggleItem=function(a){"undefined"==typeof b.selectedOptions&&(b.selectedOptions=[]);var c=b.selectedOptions.indexOf(a),d=c!==-1;if(d)b.unselectedOptions.push(b.selectedOptions[c]),b.selectedOptions.splice(c,1);else if(!d&&(0===b.selectionLimit||b.selectedOptions.lengthb.searchLimit)return!1;var d=b.getDisplay(c);if(d){var e=d.toLowerCase().indexOf(b.searchFilter.toLowerCase())>-1;return e&&a++,e}}}}}}])}(),angular.module("btorfs.multiselect.templates",["multiselect.html"]),angular.module("multiselect.html",[]).run(["$templateCache",function(a){a.put("multiselect.html",'\n')}]); \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/aai/util/AAIRestInterface.java b/vid-app-common/src/main/java/org/openecomp/aai/util/AAIRestInterface.java index 243410050..d9bb5c1f4 100755 --- a/vid-app-common/src/main/java/org/openecomp/aai/util/AAIRestInterface.java +++ b/vid-app-common/src/main/java/org/openecomp/aai/util/AAIRestInterface.java @@ -253,6 +253,54 @@ public class AAIRestInterface { return false; } + + /** + * Rest put. + * + * @param fromAppId the from app id + * @param transId the trans id + * @param path the path + * @param payload the payload + * @param xml the xml + * @return the string + */ + public Response RestPut(String fromAppId, String transId, String path, String payload, boolean xml) { + String methodName = "RestPost"; + String url=""; + transId = UUID.randomUUID().toString(); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + + String responseType = "application/json"; + if (xml) + responseType = "application/xml"; + + initRestClient(); + + url = SystemProperties.getProperty(AAIProperties.AAI_SERVER_URL) + path; + + final Response cres = client.target(url) + .request() + .accept(responseType) + .header("X-TransactionId", transId) + .header("X-FromAppId", fromAppId) + .put(Entity.entity(payload, MediaType.APPLICATION_JSON)); + + if (cres.getStatus() == 200 && cres.getStatus() <= 299) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + } else { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName +" with status="+cres.getStatus()+", url="+url); + } + return cres; + } catch (Exception e) { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + } + return null; + } + + /** * Rest post. diff --git a/vid-app-common/src/main/java/org/openecomp/vid/RelatedTo.java b/vid-app-common/src/main/java/org/openecomp/vid/RelatedTo.java new file mode 100644 index 000000000..48ca49705 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/RelatedTo.java @@ -0,0 +1,36 @@ +package org.openecomp.vid; + +import com.fasterxml.jackson.annotation.*; +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "id", + "node-type", + "url" +}) +public class RelatedTo { + + @JsonProperty("id") + public String id; + @JsonProperty("node-type") + public String nodeType; + @JsonProperty("url") + public String url; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClient.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClient.java index af1f4042a..0f07f2066 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClient.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClient.java @@ -7,9 +7,8 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.openecomp.aai.util.AAIRestInterface; -import org.apache.tiles.request.ApplicationContext; import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.openecomp.portalsdk.core.web.support.UserUtils; +import org.openecomp.vid.aai.model.ServiceRelationships; import org.openecomp.vid.aai.model.AaiGetServicesRequestModel.GetServicesAAIRespone; import org.openecomp.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.openecomp.vid.model.SubscriberList; @@ -25,6 +24,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; +import java.util.List; import java.util.UUID; @@ -33,252 +33,320 @@ import java.util.UUID; */ public class AaiClient implements AaiClientInterface { - /** - * The Constant dateFormat. - */ - final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); - protected String fromAppId = "VidAaiController"; - @Autowired - ServletContext servletContext; - /** - * The logger - */ - - EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AaiClient.class); - - - public AaiClient() { - // certiPath = getCertificatesFile().getAbsolutePath(); - // depth = "0"; - } - - public AaiClient(ServletContext context) { - servletContext = context; - } - - - - private static String checkForNull(String local) { - if (local != null) - return local; - else - return ""; - - } - + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + protected String fromAppId = "VidAaiController"; + @Autowired + ServletContext servletContext; + /** + * The logger + */ + + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AaiClient.class); + + + public AaiClient() { + // certiPath = getCertificatesFile().getAbsolutePath(); + // depth = "0"; + } + + public AaiClient(ServletContext context) { + servletContext = context; + } + + + private static String checkForNull(String local) { + if (local != null) + return local; + else + return ""; + + } + + @Override + public AaiResponse getAllSubscribers() { + String certiPath = getCertificatesFile().getAbsolutePath(); + String depth = "0"; + Response resp = doAaiGet(certiPath, "business/customers?subscriber-type=INFRA&depth=" + depth, false); + return proccessAaiResponse(resp, SubscriberList.class, null); + } + + + @Override + public AaiResponse getAllAicZones() { + String certiPath = getCertificatesFile().getAbsolutePath(); + Response resp = doAaiGet(certiPath, "network/zones", false); + AaiResponse aaiAicZones = proccessAaiResponse(resp, AicZones.class, null); + return aaiAicZones; + } + + @Override - public AaiResponse getAllSubscribers() { + public AaiResponse getAicZoneForPnf(String globalCustomerId , String serviceType , String serviceId) { String certiPath = getCertificatesFile().getAbsolutePath(); - String depth = "0"; - Response resp = doAaiGet(certiPath, "business/customers?subscriber-type=INFRA&depth=" + depth, false); - UserUtils userUtils = new UserUtils(); - return proccessAaiResponse(resp, SubscriberList.class,null); - } - - - @Override - public AaiResponse getAllAicZones() { - String certiPath = getCertificatesFile().getAbsolutePath(); - Response resp = doAaiGet(certiPath, "network/zones" , false); - AaiResponse aaiAicZones = proccessAaiResponse(resp, AicZones.class,null); - return aaiAicZones; - } - - @Override - public AaiResponse getSubscriberData(String subscriberId) { - - File certiPath = getCertificatesFile(); - String depth = "2"; - AaiResponse subscriberDataResponse; - Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId + "?depth=" + depth, false); - subscriberDataResponse = proccessAaiResponse(resp, Services.class,null); - return subscriberDataResponse; - } - - @Override - public AaiResponse getServices() { - File certiPath = getCertificatesFile(); - Response resp = doAaiGet(certiPath.getAbsolutePath(), "service-design-and-creation/services", false); - AaiResponse getServicesResponse = proccessAaiResponse(resp, GetServicesAAIRespone.class,null); - - return getServicesResponse; + String aicZonePath = "business/customers/customer/" + globalCustomerId + "/service-subscriptions/service-subscription/" + serviceType + "/service-instances/service-instance/" + serviceId; + Response resp = doAaiGet(certiPath , aicZonePath , false); + AaiResponse aaiResponse = proccessAaiResponse(resp , ServiceRelationships.class , null); + ServiceRelationships serviceRelationships = (ServiceRelationships)aaiResponse.getT(); + String aicZone = serviceRelationships.getRelationshipList().getRelationship().get(0).getRelatedToPropertyList().get(0).getPropertyValue(); + AaiResponse aaiAicZonaForPnfResponse = new AaiResponse(aicZone , null ,HttpStatus.SC_OK); + return aaiAicZonaForPnfResponse; } + + + @Override + public AaiResponse getVNFData() { + String certiPath = getCertificatesFile().getAbsolutePath(); + String payload = "{\"start\": [\"/business/customers/customer/e433710f-9217-458d-a79d-1c7aff376d89/service-subscriptions/service-subscription/VIRTUAL%20USP/service-instances/service-instance/3f93c7cb-2fd0-4557-9514-e189b7b04f9d\"], \"query\": \"query/vnf-topology-fromServiceInstance\"}"; + Response resp = doAaiPut(certiPath, "query?format=simple", payload, false); + return proccessAaiResponse(resp, AaiGetVnfResponse.class, null); + + } + + @Override + public Response getVNFData(String globalSubscriberId, String serviceType) { + String certiPath = getCertificatesFile().getAbsolutePath(); + String payload = "{\"start\": [\"business/customers/customer/" + globalSubscriberId + "/service-subscriptions/service-subscription/"+ serviceType +"/service-instances\"]," + + "\"query\": \"query/vnf-topology-fromServiceInstance\"}"; + return doAaiPut(certiPath, "query?format=simple", payload, false); + + } + + @Override + public AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId) { + String certiPath = getCertificatesFile().getAbsolutePath(); + String payload = "{\"start\": [\"/business/customers/customer/" + globalSubscriberId + "/service-subscriptions/service-subscription/" + serviceType + "/service-instances/service-instance/" + serviceInstanceId + "\"], \"query\": \"query/vnf-topology-fromServiceInstance\"}"; + Response resp = doAaiPut(certiPath, "query?format=simple", payload, false); + return proccessAaiResponse(resp, AaiGetVnfResponse.class, null); + } + + @Override + public Response getVersionByInvariantId(List modelInvariantId) { + File certiPath = getCertificatesFile(); + StringBuilder sb = new StringBuilder(); + for (String id : modelInvariantId){ + sb.append("&model-invariant-id="); + sb.append(id); + + } + Response resp = doAaiGet(certiPath.getAbsolutePath(), "service-design-and-creation/models?depth=2"+ sb.toString(), false); + return resp; + } + + @Override + public AaiResponse getSubscriberData(String subscriberId) { + File certiPath = getCertificatesFile(); + String depth = "2"; + AaiResponse subscriberDataResponse; + Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId + "?depth=" + depth, false); + subscriberDataResponse = proccessAaiResponse(resp, Services.class, null); + return subscriberDataResponse; + } + + @Override + public AaiResponse getServices() { + File certiPath = getCertificatesFile(); + Response resp = doAaiGet(certiPath.getAbsolutePath(), "service-design-and-creation/services", false); + AaiResponse getServicesResponse = proccessAaiResponse(resp, GetServicesAAIRespone.class, null); + + return getServicesResponse; + } + + @Override + public AaiResponse getTenants(String globalCustomerId, String serviceType) { + File certiPath = getCertificatesFile(); + String url = "business/customers/customer/" + globalCustomerId + "/service-subscriptions/service-subscription/" + serviceType; + + Response resp = doAaiGet(certiPath.getAbsolutePath(), url, false); + String responseAsString = parseForTenantsByServiceSubscription(resp.readEntity(String.class)); + + AaiResponse getTenantsResponse = proccessAaiResponse(resp, GetTenantsResponse[].class, responseAsString); + return getTenantsResponse; + } + + private AaiResponse proccessAaiResponse(Response resp, Class classType, String responseBody) { + AaiResponse subscriberDataResponse; + if (resp == null) { + subscriberDataResponse = new AaiResponse<>(null, null, HttpStatus.SC_INTERNAL_SERVER_ERROR); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "Invalid response from AAI"); + } else { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscribers() resp=" + resp.getStatusInfo().toString()); + if (resp.getStatus() != HttpStatus.SC_OK) { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "Invalid response from AAI"); + subscriberDataResponse = new AaiResponse<>(null, resp.readEntity(String.class), resp.getStatus()); + } else { + String finalResponse; + try { + if (responseBody != null) { + finalResponse = responseBody; + } else { + finalResponse = resp.readEntity(String.class); + } + + subscriberDataResponse = new AaiResponse<>((new ObjectMapper().readValue(finalResponse, classType)), null, HttpStatus.SC_OK); + + } catch (IOException e) { + subscriberDataResponse = new AaiResponse<>(null, null, HttpStatus.SC_INTERNAL_SERVER_ERROR); + } + + } + } + return subscriberDataResponse; + } + + private File getCertificatesFile() { + if (servletContext != null) + return new File(servletContext.getRealPath("/WEB-INF/cert/")); + return null; + } + + @SuppressWarnings("all") + protected Response doAaiGet(String certiPath, String uri, boolean xml) { + String methodName = "doAaiGet"; + String transId = UUID.randomUUID().toString(); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + Response resp = null; + try { + + AAIRestInterface restContrller = new AAIRestInterface(certiPath); + resp = restContrller.RestGet(fromAppId, transId, uri, xml); + + } catch (WebApplicationException e) { + final String message = ((BadRequestException) e).getResponse().readEntity(String.class); + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + } + + return resp; + } + + private String parseForTenantsByServiceSubscription(String resp) { + String tenantList = ""; + + try { + JSONParser jsonParser = new JSONParser(); + + JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); + + return parseServiceSubscriptionObjectForTenants(jsonObject); + } catch (Exception ex) { + + } + + return tenantList; + } + + protected Response doAaiPut(String certiPath, String uri, String payload, boolean xml) { + String methodName = "doAaiPut"; + String transId = UUID.randomUUID().toString(); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + Response resp = null; + try { - @Override - public AaiResponse getTenants(String globalCustomerId, String serviceType) { - File certiPath = getCertificatesFile(); - String url = "business/customers/customer/" + globalCustomerId + "/service-subscriptions/service-subscription/" + serviceType; - - Response resp = doAaiGet(certiPath.getAbsolutePath(), url, false); - String responseAsString = parseForTenantsByServiceSubscription(resp.readEntity(String.class)); - - AaiResponse getTenantsResponse = proccessAaiResponse(resp, GetTenantsResponse[].class,responseAsString); - return getTenantsResponse; - } - - private AaiResponse proccessAaiResponse(Response resp, Class classType,String responseBody) { - AaiResponse subscriberDataResponse; - if (resp == null) { - subscriberDataResponse = new AaiResponse<>(null, null, HttpStatus.SC_INTERNAL_SERVER_ERROR); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "Invalid response from AAI"); - } else { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscribers() resp=" + resp.getStatusInfo().toString()); - if (resp.getStatus() != HttpStatus.SC_OK) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "Invalid response from AAI"); - subscriberDataResponse = new AaiResponse<>(null, resp.readEntity(String.class), resp.getStatus()); - } else { - String finalResponse; - try { - if (responseBody != null){ - finalResponse = responseBody; - } - else{ - finalResponse = resp.readEntity(String.class);; - } - - subscriberDataResponse = new AaiResponse<>((new ObjectMapper().readValue(finalResponse, classType)), null, HttpStatus.SC_OK); - - } catch (IOException e) { - subscriberDataResponse = new AaiResponse<>(null, null, HttpStatus.SC_INTERNAL_SERVER_ERROR); - } - - } - } - return subscriberDataResponse; - } - - private File getCertificatesFile() { - if (servletContext != null) - return new File(servletContext.getRealPath("/WEB-INF/cert/")); - return null; - } - - @SuppressWarnings("all") - protected Response doAaiGet(String certiPath, String uri, boolean xml) { - String methodName = "getSubscriberList"; - String transId = UUID.randomUUID().toString(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - - Response resp = null; - try { - - AAIRestInterface restContrller = new AAIRestInterface(certiPath); - resp = restContrller.RestGet(fromAppId, transId, uri, xml); - - } catch (WebApplicationException e) { - final String message = ((BadRequestException) e).getResponse().readEntity(String.class); - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - } - - return resp; - } - - private String parseForTenantsByServiceSubscription(String resp) { - String tenantList = ""; - - try { - JSONParser jsonParser = new JSONParser(); - - JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); - - return parseServiceSubscriptionObjectForTenants(jsonObject); - } catch (Exception ex) { - - } - - return tenantList; - } + AAIRestInterface restContrller = new AAIRestInterface(certiPath); + resp = restContrller.RestPut(fromAppId, transId, uri, payload, xml); + + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + } + + return resp; + } + public static String parseServiceSubscriptionObjectForTenants(JSONObject jsonObject) { + + JSONArray tenantArray = new JSONArray(); + boolean bconvert = false; + + try { + JSONObject relationShipListsObj = (JSONObject) jsonObject.get("relationship-list"); + if (relationShipListsObj != null) { + JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); + if (rShipArray != null) { + Iterator i1 = rShipArray.iterator(); - public static String parseServiceSubscriptionObjectForTenants(JSONObject jsonObject) { + while (i1.hasNext()) { - JSONArray tenantArray = new JSONArray(); - boolean bconvert = false; + JSONObject inner1Obj = (JSONObject) i1.next(); - try { - JSONObject relationShipListsObj = (JSONObject) jsonObject.get("relationship-list"); - if (relationShipListsObj != null) { - JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); - if (rShipArray != null) { - Iterator i1 = rShipArray.iterator(); + if (inner1Obj == null) + continue; - while (i1.hasNext()) { + String relatedTo = checkForNull((String) inner1Obj.get("related-to")); + if (relatedTo.equalsIgnoreCase("tenant")) { + JSONObject tenantNewObj = new JSONObject(); - JSONObject inner1Obj = (JSONObject) i1.next(); + String relatedLink = checkForNull((String) inner1Obj.get("related-link")); + tenantNewObj.put("link", relatedLink); - if (inner1Obj == null) - continue; + JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); + if (rDataArray != null) { + Iterator i2 = rDataArray.iterator(); - String relatedTo = checkForNull((String) inner1Obj.get("related-to")); - if (relatedTo.equalsIgnoreCase("tenant")) { - JSONObject tenantNewObj = new JSONObject(); + while (i2.hasNext()) { + JSONObject inner2Obj = (JSONObject) i2.next(); - String relatedLink = checkForNull((String) inner1Obj.get("related-link")); - tenantNewObj.put("link", relatedLink); + if (inner2Obj == null) + continue; - JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); - if (rDataArray != null) { - Iterator i2 = rDataArray.iterator(); + String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); + String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); + if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { + tenantNewObj.put("cloudOwner", rShipVal); + } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { + tenantNewObj.put("cloudRegionID", rShipVal); + } - while (i2.hasNext()) { - JSONObject inner2Obj = (JSONObject) i2.next(); + if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { + tenantNewObj.put("tenantID", rShipVal); + } + } + } - if (inner2Obj == null) - continue; + JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); + if (relatedTPropArray != null) { + Iterator i3 = relatedTPropArray.iterator(); - String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); - String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); - if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { - tenantNewObj.put("cloudOwner", rShipVal); - } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { - tenantNewObj.put("cloudRegionID", rShipVal); - } + while (i3.hasNext()) { + JSONObject inner3Obj = (JSONObject) i3.next(); - if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { - tenantNewObj.put("tenantID", rShipVal); - } - } - } + if (inner3Obj == null) + continue; - JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); - if (relatedTPropArray != null) { - Iterator i3 = relatedTPropArray.iterator(); + String propKey = checkForNull((String) inner3Obj.get("property-key")); + String propVal = checkForNull((String) inner3Obj.get("property-value")); + if (propKey.equalsIgnoreCase("tenant.tenant-name")) { + tenantNewObj.put("tenantName", propVal); + } + } + } + bconvert = true; + tenantArray.add(tenantNewObj); + } + } - while (i3.hasNext()) { - JSONObject inner3Obj = (JSONObject) i3.next(); + } + } + } catch (NullPointerException ex) { - if (inner3Obj == null) - continue; - String propKey = checkForNull((String) inner3Obj.get("property-key")); - String propVal = checkForNull((String) inner3Obj.get("property-value")); - if (propKey.equalsIgnoreCase("tenant.tenant-name")) { - tenantNewObj.put("tenantName", propVal); - } - } - } - bconvert = true; - tenantArray.add(tenantNewObj); - } - } + } - } - } - } catch (NullPointerException ex) { + if (bconvert) + return tenantArray.toJSONString(); + else + return ""; + } - } - - if (bconvert) - return tenantArray.toJSONString(); - else - return ""; - - } } \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClientInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClientInterface.java index fdaf602f4..f1b1ba2df 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClientInterface.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiClientInterface.java @@ -3,6 +3,7 @@ package org.openecomp.vid.aai; import org.openecomp.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.openecomp.vid.model.SubscriberList; +import javax.ws.rs.core.Response; import java.util.List; /** @@ -19,4 +20,14 @@ public interface AaiClientInterface { AaiResponse getTenants(String globalCustomerId, String serviceType); AaiResponse getAllAicZones(); + + AaiResponse getAicZoneForPnf(String globalCustomerId , String serviceType , String serviceId); + + AaiResponse getVNFData(); + + Response getVNFData(String globalSubscriberId, String serviceType); + + AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId); + + Response getVersionByInvariantId(List modelInvariantId); } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiGetVnfResponse.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiGetVnfResponse.java new file mode 100644 index 000000000..7c9d44b12 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/AaiGetVnfResponse.java @@ -0,0 +1,28 @@ +package org.openecomp.vid.aai; + +import com.fasterxml.jackson.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "results" +}) +public class AaiGetVnfResponse { + @JsonProperty("results") + public List results = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/ServiceProperties.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/ServiceProperties.java new file mode 100644 index 000000000..113f113d3 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/ServiceProperties.java @@ -0,0 +1,90 @@ +package org.openecomp.vid.aai; + +import com.fasterxml.jackson.annotation.*; +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "service-instance-id", + "service-instance-name", + "model-invariant-id", + "model-version-id", + "resource-version", + "orchestration-status", + "global-customer-id", + "subscriber-name", + "subscriber-type", + "vnf-id", + "vnf-name", + "vnf-type", + "service-id", + "prov-status", + "in-maint", + "is-closed-loop-disabled", + "model-customization-id", + "nf-type", + "nf-function", + "nf-role", + "nf-naming-code" +}) +public class ServiceProperties { + + @JsonProperty("service-instance-id") + public String serviceInstanceId; + @JsonProperty("service-instance-name") + public String serviceInstanceName; + @JsonProperty("model-invariant-id") + public String modelInvariantId; + @JsonProperty("model-version-id") + public String modelVersionId; + @JsonProperty("resource-version") + public String resourceVersion; + @JsonProperty("orchestration-status") + public String orchestrationStatus; + @JsonProperty("global-customer-id") + public String globalCustomerId; + @JsonProperty("subscriber-name") + public String subscriberName; + @JsonProperty("subscriber-type") + public String subscriberType; + @JsonProperty("vnf-id") + public String vnfId; + @JsonProperty("vnf-name") + public String vnfName; + @JsonProperty("vnf-type") + public String vnfType; + @JsonProperty("service-id") + public String serviceId; + @JsonProperty("prov-status") + public String provStatus; + @JsonProperty("in-maint") + public Boolean inMaint; + @JsonProperty("is-closed-loop-disabled") + public Boolean isClosedLoopDisabled; + @JsonProperty("model-customization-id") + public String modelCustomizationId; + @JsonProperty("nf-type") + public String nfType; + @JsonProperty("nf-function") + public String nfFunction; + @JsonProperty("nf-role") + public String nfRole; + @JsonProperty("nf-naming-code") + public String nfNamingCode; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/VnfResult.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/VnfResult.java new file mode 100644 index 000000000..b8294e519 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/VnfResult.java @@ -0,0 +1,44 @@ +package org.openecomp.vid.aai; + +import com.fasterxml.jackson.annotation.*; +import org.codehaus.jackson.annotate.JsonProperty; +import org.openecomp.vid.RelatedTo; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "id", + "node-type", + "url", + "properties", + "related-to" +}) +public class VnfResult { + + @JsonProperty("id") + public String id; + @JsonProperty("node-type") + public String nodeType; + @JsonProperty("url") + public String url; + @JsonProperty("properties") + public ServiceProperties properties; + @JsonProperty("related-to") + public List relatedTo = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelatedToProperty.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelatedToProperty.java new file mode 100644 index 000000000..c9f28ed69 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelatedToProperty.java @@ -0,0 +1,34 @@ +package org.openecomp.vid.aai.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class RelatedToProperty { + + public String getPropertyKey() { + return propertyKey; + } + + + public void setPropertyKey(String propertyKey) { + this.propertyKey = propertyKey; + } + + + public String getPropertyValue() { + return propertyValue; + } + + + public void setPropertyValue(String propertyValue) { + this.propertyValue = propertyValue; + } + + + @JsonProperty("property-key") + public String propertyKey; + + + @JsonProperty("property-value") + public String propertyValue; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/model/Relationship.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/Relationship.java new file mode 100644 index 000000000..796094192 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/Relationship.java @@ -0,0 +1,55 @@ +package org.openecomp.vid.aai.model; + +import java.util.List; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class Relationship { + + @JsonProperty("related-to") + public String relatedTo; + + @JsonProperty("related-link") + public String relatedLink; + + @JsonProperty("relationship-data") + public List relationshipData; + + @JsonProperty("related-to-property") + public List relatedToProperty; + + + public String getRelatedTo() { + return relatedTo; + } + + public void setRelatedTo(String relatedTo) { + this.relatedTo = relatedTo; + } + + public String getRelatedLink() { + return relatedLink; + } + + public void setRelatedLink(String relatedLink) { + this.relatedLink = relatedLink; + } + + public List getRelationDataList() { + return relationshipData; + } + + public void setRelationDataList(List relationDataList) { + this.relationshipData = relationDataList; + } + + public List getRelatedToPropertyList() { + return relatedToProperty; + } + + public void setRelatedToPropertyList(List relatedToPropertyList) { + this.relatedToProperty = relatedToPropertyList; + } + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipData.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipData.java new file mode 100644 index 000000000..21af2f5d6 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipData.java @@ -0,0 +1,29 @@ +package org.openecomp.vid.aai.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class RelationshipData { + + public String getRelationshipKey() { + return relationshipKey; + } + + public void setRelationshipKey(String relationshipKey) { + this.relationshipKey = relationshipKey; + } + + public String getRelationshipValue() { + return relationshipValue; + } + + public void setRelationshipValue(String relationshipValue) { + this.relationshipValue = relationshipValue; + } + + @JsonProperty("relationship-key") + public String relationshipKey; + + @JsonProperty("relationship-value") + public String relationshipValue; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipList.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipList.java new file mode 100644 index 000000000..cdb7af46b --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/RelationshipList.java @@ -0,0 +1,24 @@ +package org.openecomp.vid.aai.model; + +import java.util.List; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class RelationshipList { + + + public List getRelationship() { + return relationship; + } + + public void setRelationship(List relationship) { + this.relationship = relationship; + } + + @JsonProperty("relationship") + public List relationship; + + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/aai/model/ServiceRelationships.java b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/ServiceRelationships.java new file mode 100644 index 000000000..9bedd8545 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/aai/model/ServiceRelationships.java @@ -0,0 +1,90 @@ +package org.openecomp.vid.aai.model; + +import org.codehaus.jackson.annotate.JsonProperty; + +public class ServiceRelationships { + + @JsonProperty("service-instance-id") + public String serviceInstanceId; + + @JsonProperty("service-instance-name") + public String serviceInstanceName; + + @JsonProperty("model-invariant-id") + public String modelInvariantId; + + @JsonProperty("model-version-id") + public String modelVersionId; + + @JsonProperty("resource-version") + public String resourceVersion; + + @JsonProperty("orchestration-status") + public String orchestrationStatus; + + @JsonProperty("relationship-list") + public RelationshipList relationshipList; + + + public String getServiceInstanceId() { + return serviceInstanceId; + } + + public void setServiceInstanceId(String serviceInstanceId) { + this.serviceInstanceId = serviceInstanceId; + } + + public String getServiceInstanceName() { + return serviceInstanceName; + } + + public void setServiceInstanceName(String serviceInstanceName) { + this.serviceInstanceName = serviceInstanceName; + } + + public String getModelInvariantId() { + return modelInvariantId; + } + + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + public String getModelVersionId() { + return modelVersionId; + } + + public void setModelVersionId(String modelVersionId) { + this.modelVersionId = modelVersionId; + } + + public String getResourceVersion() { + return resourceVersion; + } + + public void setResourceVersion(String resourceVersion) { + this.resourceVersion = resourceVersion; + } + + public String getOrchestrationStatus() { + return orchestrationStatus; + } + + public void setOrchestrationStatus(String orchestrationStatus) { + this.orchestrationStatus = orchestrationStatus; + } + + public RelationshipList getRelationshipList() { + return relationshipList; + } + + public void setRelationshipList(RelationshipList relationshipList) { + this.relationshipList = relationshipList; + } + + + + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/asdc/beans/tosca/ToscaMetadata.java b/vid-app-common/src/main/java/org/openecomp/vid/asdc/beans/tosca/ToscaMetadata.java index 41c7ca5ba..d42c1f150 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/asdc/beans/tosca/ToscaMetadata.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/asdc/beans/tosca/ToscaMetadata.java @@ -61,9 +61,6 @@ public class ToscaMetadata { /** The resource vendor release. */ private String resourceVendorRelease; - /** the resourceVendorModelNumber */ - private String resourceVendorModelNumber; - /** The service ecomp naming. */ private String serviceEcompNaming; @@ -91,11 +88,6 @@ public class ToscaMetadata { /** The vf module model version. */ private String vfModuleModelVersion; - - /** serviceType */ - private String serviceType; - /** serviceRole */ - private String serviceRole; /** * Instantiates a new tosca metadata. @@ -466,26 +458,4 @@ public class ToscaMetadata { return vfModuleModelCustomizationUUID; } - - /** serviceType */ - public String getServiceType() { - return serviceType; - } - public void setServiceType(String serviceType) { - this.serviceType= serviceType; - } - /** serviceRole */ - public String getServiceRole() { - return serviceRole; - } - public void setServiceRole(String serviceRole) { - this.serviceRole= serviceRole; - } - /** resourceVendorModelNumber */ - public String getResourceVendorModelNumber() { - return resourceVendorModelNumber; - } - public void setResourceVendorModelNumber(String resourceVendorModelNumber) { - this.resourceVendorModelNumber= resourceVendorModelNumber; - } } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/asdc/parser/ToscaParserImpl2.java b/vid-app-common/src/main/java/org/openecomp/vid/asdc/parser/ToscaParserImpl2.java index 3f0dd8c31..e2b32fa8c 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/asdc/parser/ToscaParserImpl2.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/asdc/parser/ToscaParserImpl2.java @@ -191,6 +191,8 @@ public class ToscaParserImpl2 { volumeGroup.setModelCustomizationName(group.getMetadata().getValue(Constants.vfModuleModelName)); volumeGroup.setVersion(group.getMetadata().getValue(Constants.vfModuleModelVersion)); volumeGroup.setUuid(group.getMetadata().getValue(Constants.vfModuleModelUUID)); + volumeGroup.setCustomizationUuid(group.getMetadata().getValue(Constants.vfModuleModelCustomizationUUID)); + return volumeGroup; } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementRequest.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementRequest.java new file mode 100644 index 000000000..adcb54683 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementRequest.java @@ -0,0 +1,63 @@ +package org.openecomp.vid.changeManagement; + +import java.util.List; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonPropertyOrder({ + "requestDetails", + "requestType" +}) + +public class ChangeManagementRequest { + + public ChangeManagementRequest() {} + + @JsonProperty("requestDetails") + private List requestDetails; + + @JsonProperty("requestType") + private String requestType; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("requestDetails") + public List getRequestDetails() { + return requestDetails; + } + + @JsonProperty("requestDetails") + public void setRequestDetails(List requestDetails) { + this.requestDetails = requestDetails; + } + + @JsonProperty("requestType") + public String getRequestType() { + return requestType; + } + + @JsonProperty("requestType") + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementResponse.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementResponse.java new file mode 100644 index 000000000..10ba035d6 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ChangeManagementResponse.java @@ -0,0 +1,19 @@ +package org.openecomp.vid.changeManagement; + +import java.util.ArrayList; +import java.util.List; + +public class ChangeManagementResponse { + public List cmResponses = null; + + + + public ChangeManagementResponse(String vnfName) { + List cmResponses = new ArrayList<>(); + cmResponses.add(new CmResponse(vnfName)); + this.cmResponses = cmResponses; + + } + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CloudConfiguration.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CloudConfiguration.java new file mode 100644 index 000000000..a5debc6db --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CloudConfiguration.java @@ -0,0 +1,55 @@ +package org.openecomp.vid.changeManagement; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"lcpCloudRegionId", +"tenantId" +}) +public class CloudConfiguration { + @JsonProperty("lcpCloudRegionId") + private String lcpCloudRegionId; + @JsonProperty("tenantId") + private String tenantId; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("lcpCloudRegionId") + public String getLcpCloudRegionId() { + return lcpCloudRegionId; + } + + @JsonProperty("lcpCloudRegionId") + public void setLcpCloudRegionId(String lcpCloudRegionId) { + this.lcpCloudRegionId = lcpCloudRegionId; + } + + @JsonProperty("tenantId") + public String getTenantId() { + return tenantId; + } + + @JsonProperty("tenantId") + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CmResponse.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CmResponse.java new file mode 100644 index 000000000..70e09d83c --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/CmResponse.java @@ -0,0 +1,17 @@ +package org.openecomp.vid.changeManagement; + +public class CmResponse { + + public String orchestratorRequestId; + public String serviceInstanceId; + public String vnfInstanceId; + public String vnfName; + + public CmResponse(String vnfName){ + this.orchestratorRequestId = "Request Id"; + this.serviceInstanceId = "Service instance Id"; + this.vnfInstanceId = "Vnf instance Id"; + this.vnfName = vnfName; + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/LeanCloudConfiguration.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/LeanCloudConfiguration.java new file mode 100644 index 000000000..663ff8c49 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/LeanCloudConfiguration.java @@ -0,0 +1,20 @@ +package org.openecomp.vid.changeManagement; + +/** + * Created by Oren on 9/5/17. + */ +public class LeanCloudConfiguration { + + public LeanCloudConfiguration() { + } + + public LeanCloudConfiguration(org.openecomp.vid.domain.mso.CloudConfiguration cloudConfiguration) { + this.tenantId = cloudConfiguration.getTenantId(); + this.lcpCloudRegionId = cloudConfiguration.getLcpCloudRegionId(); + + } + public String lcpCloudRegionId; + + public String tenantId; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfo.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfo.java new file mode 100644 index 000000000..517628ca0 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfo.java @@ -0,0 +1,138 @@ +package org.openecomp.vid.changeManagement; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"modelType", +"modelInvariantId", +"modelVersionId", +"modelName", +"modelVersion", +"modelCustomizationName", +"modelCustomizationId" +}) +public class ModelInfo { + + public ModelInfo(){ + + } + + public ModelInfo(org.openecomp.vid.domain.mso.ModelInfo modelInfo){ + this.setModelType(modelInfo.getModelType().toString()); + this.setModelInvariantId(modelInfo.getModelInvariantId()); + this.setModelVersionId(modelInfo.getModelNameVersionId()); + this.setModelName(modelInfo.getModelName()); + this.setModelVersion(modelInfo.getModelVersion()); + this.setModelCustomizationId(modelInfo.getModelCustomizationId()); + this.setModelVersionId(modelInfo.getModelVersionId()); + } + + + @JsonProperty("modelType") + private String modelType; + @JsonProperty("modelInvariantId") + private String modelInvariantId; + @JsonProperty("modelVersionId") + private String modelVersionId; + @JsonProperty("modelName") + private String modelName; + @JsonProperty("modelVersion") + private String modelVersion; + @JsonProperty("modelCustomizationName") + private String modelCustomizationName; + @JsonProperty("modelCustomizationId") + private String modelCustomizationId; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("modelType") + public String getModelType() { + return modelType; + } + + @JsonProperty("modelType") + public void setModelType(String modelType) { + this.modelType = modelType; + } + + @JsonProperty("modelInvariantId") + public String getModelInvariantId() { + return modelInvariantId; + } + + @JsonProperty("modelInvariantId") + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + @JsonProperty("modelVersionId") + public String getModelVersionId() { + return modelVersionId; + } + + @JsonProperty("modelVersionId") + public void setModelVersionId(String modelVersionId) { + this.modelVersionId = modelVersionId; + } + + @JsonProperty("modelName") + public String getModelName() { + return modelName; + } + + @JsonProperty("modelName") + public void setModelName(String modelName) { + this.modelName = modelName; + } + + @JsonProperty("modelVersion") + public String getModelVersion() { + return modelVersion; + } + + @JsonProperty("modelVersion") + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + @JsonProperty("modelCustomizationName") + public String getModelCustomizationName() { + return modelCustomizationName; + } + + @JsonProperty("modelCustomizationName") + public void setModelCustomizationName(String modelCustomizationName) { + this.modelCustomizationName = modelCustomizationName; + } + + @JsonProperty("modelCustomizationId") + public String getModelCustomizationId() { + return modelCustomizationId; + } + + @JsonProperty("modelCustomizationId") + public void setModelCustomizationId(String modelCustomizationId) { + this.modelCustomizationId = modelCustomizationId; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfoOfRelatedInstance.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfoOfRelatedInstance.java new file mode 100644 index 000000000..c60ed2f77 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/ModelInfoOfRelatedInstance.java @@ -0,0 +1,122 @@ +package org.openecomp.vid.changeManagement; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"modelType", +"modelInvariantId", +"modelVersionId", +"modelName", +"modelVersion", +"modelCustomizationName", +"modelCustomizationId" +}) + +public class ModelInfoOfRelatedInstance { + + @JsonProperty("modelType") + private String modelType; + @JsonProperty("modelInvariantId") + private String modelInvariantId; + @JsonProperty("modelVersionId") + private String modelVersionId; + @JsonProperty("modelName") + private String modelName; + @JsonProperty("modelVersion") + private String modelVersion; + @JsonProperty("modelCustomizationName") + private String modelCustomizationName; + @JsonProperty("modelCustomizationId") + private String modelCustomizationId; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("modelType") + public String getModelType() { + return modelType; + } + + @JsonProperty("modelType") + public void setModelType(String modelType) { + this.modelType = modelType; + } + + @JsonProperty("modelInvariantId") + public String getModelInvariantId() { + return modelInvariantId; + } + + @JsonProperty("modelInvariantId") + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + @JsonProperty("modelVersionId") + public String getModelVersionId() { + return modelVersionId; + } + + @JsonProperty("modelVersionId") + public void setModelVersionId(String modelVersionId) { + this.modelVersionId = modelVersionId; + } + + @JsonProperty("modelName") + public String getModelName() { + return modelName; + } + + @JsonProperty("modelName") + public void setModelName(String modelName) { + this.modelName = modelName; + } + + @JsonProperty("modelVersion") + public String getModelVersion() { + return modelVersion; + } + + @JsonProperty("modelVersion") + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + @JsonProperty("modelCustomizationName") + public String getModelCustomizationName() { + return modelCustomizationName; + } + + @JsonProperty("modelCustomizationName") + public void setModelCustomizationName(String modelCustomizationName) { + this.modelCustomizationName = modelCustomizationName; + } + + @JsonProperty("modelCustomizationId") + public String getModelCustomizationId() { + return modelCustomizationId; + } + + @JsonProperty("modelCustomizationId") + public void setModelCustomizationId(String modelCustomizationId) { + this.modelCustomizationId = modelCustomizationId; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/MsoRequestDetails.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/MsoRequestDetails.java new file mode 100644 index 000000000..9e442f28b --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/MsoRequestDetails.java @@ -0,0 +1,31 @@ +package org.openecomp.vid.changeManagement; + + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Oren on 9/5/17. + */ +public class MsoRequestDetails { + + public ModelInfo modelInfo; + + public LeanCloudConfiguration cloudConfiguration; + + public UpdateRequestInfo requestInfo; + + public List relatedInstanceList; + + public RequestParameters requestParameters; + + public MsoRequestDetails(RequestDetails r) { + this.modelInfo = new ModelInfo(r.getModelInfo()); + this.cloudConfiguration = new LeanCloudConfiguration(r.getCloudConfiguration()); + this.requestInfo = new UpdateRequestInfo(r.getRequestInfo()); + this.relatedInstanceList = new ArrayList<>(); + relatedInstanceList = r.getRelatedInstList(); + + + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstance.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstance.java new file mode 100644 index 000000000..49368c20e --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstance.java @@ -0,0 +1,29 @@ +package org.openecomp.vid.changeManagement; + +import com.fasterxml.jackson.annotation.*; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "instanceId", + "modelInfo" +}) +public class RelatedInstance { + + @JsonProperty("instanceId") + public String instanceId; + + + @JsonProperty("modelInfo") + public ModelInfo modelInfo; + + @JsonGetter + public String getInstanceId() { + return instanceId; + } + + @JsonSetter + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstanceList.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstanceList.java new file mode 100644 index 000000000..21a41c3f7 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RelatedInstanceList.java @@ -0,0 +1,23 @@ +package org.openecomp.vid.changeManagement; + +import com.fasterxml.jackson.annotation.*; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "relatedInstance" +}) +public class RelatedInstanceList { + + @JsonProperty("relatedInstance") + public RelatedInstance relatedInstance; + + @JsonSetter + public RelatedInstance getRelatedInstance() { + return relatedInstance; + } + + @JsonSetter + public void setRelatedInstance(RelatedInstance relatedInstance) { + this.relatedInstance = relatedInstance; + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetails.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetails.java new file mode 100644 index 000000000..94e4c4468 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetails.java @@ -0,0 +1,56 @@ +package org.openecomp.vid.changeManagement; + +import com.fasterxml.jackson.annotation.*; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"modelInfo", +"cloudConfiguration", +"requestInfo", +"requestParameters", +"vnfName", +"vnfInstanceId" +}) +public class RequestDetails extends org.openecomp.vid.mso.rest.RequestDetails{ + + @JsonProperty("vnfName") + private String vnfName; + @JsonProperty("vnfInstanceId") + private String vnfInstanceId; + + /** The related model list. */ + @JsonProperty("relatedInstanceList") + public List relatedInstList; + + @JsonProperty("vnfName") + public String getVnfName() { + return vnfName; + } + + @JsonProperty("vnfName") + public void setVnfName(String vnfName) { + this.vnfName = vnfName; + } + @JsonProperty("vnfInstanceId") + public String getVnfInstanceId() { + return vnfInstanceId; + } + + @JsonProperty("vnfInstanceId") + public void setVnfInstanceId(String vnfInstanceId) { + this.vnfInstanceId = vnfInstanceId; + } + + @JsonGetter + public List getRelatedInstList() { + return relatedInstList; + } + + @JsonSetter + public void setRelatedInstList(List relatedInstList) { + this.relatedInstList = relatedInstList; + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetailsWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetailsWrapper.java new file mode 100644 index 000000000..2f49aff0a --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestDetailsWrapper.java @@ -0,0 +1,9 @@ +package org.openecomp.vid.changeManagement; + +/** + * Created by Oren on 9/5/17. + */ +public class RequestDetailsWrapper { + + public MsoRequestDetails requestDetails; +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestInfo.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestInfo.java new file mode 100644 index 000000000..a7236c4b1 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestInfo.java @@ -0,0 +1,69 @@ +package org.openecomp.vid.changeManagement; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"source", +"suppressRollback", +"requestorId" +}) +public class RequestInfo { + @JsonProperty("source") + private String source; + @JsonProperty("suppressRollback") + private Boolean suppressRollback; + @JsonProperty("requestorId") + private String requestorId; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("source") + public String getSource() { + return source; + } + + @JsonProperty("source") + public void setSource(String source) { + this.source = source; + } + + @JsonProperty("suppressRollback") + public Boolean getSuppressRollback() { + return suppressRollback; + } + + @JsonProperty("suppressRollback") + public void setSuppressRollback(Boolean suppressRollback) { + this.suppressRollback = suppressRollback; + } + + @JsonProperty("requestorId") + public String getRequestorId() { + return requestorId; + } + + @JsonProperty("requestorId") + public void setRequestorId(String requestorId) { + this.requestorId = requestorId; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestParameters.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestParameters.java new file mode 100644 index 000000000..37cad4735 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/RequestParameters.java @@ -0,0 +1,44 @@ +package org.openecomp.vid.changeManagement; + +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ +"usePreload" +}) + +public class RequestParameters { + + + @JsonProperty("usePreload") + private Boolean usePreload; + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("usePreload") + public Boolean getUsePreload() { + return usePreload; + } + + @JsonProperty("usePreload") + public void setUsePreload(Boolean usePreload) { + this.usePreload = usePreload; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/UpdateRequestInfo.java b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/UpdateRequestInfo.java new file mode 100644 index 000000000..ab8189484 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/changeManagement/UpdateRequestInfo.java @@ -0,0 +1,26 @@ +package org.openecomp.vid.changeManagement; + +import org.openecomp.vid.domain.mso.*; + +/** + * Created by Oren on 9/5/17. + */ +public class UpdateRequestInfo { + + public UpdateRequestInfo() { + } + + + public UpdateRequestInfo(org.openecomp.vid.domain.mso.RequestInfo requestInfo) { + this.requestorId = requestInfo.getRequestorId(); + this.suppressRollback = requestInfo.getSuppressRollback(); + this.source = requestInfo.getSource(); + } + public String source; + + public Boolean suppressRollback; + + public String requestorId; + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/AaiController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/AaiController.java index c0b6a5140..a8bdf39bb 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/controller/AaiController.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/AaiController.java @@ -35,6 +35,7 @@ import org.openecomp.vid.aai.AaiResponse; import org.openecomp.vid.aai.SubscriberData; import org.openecomp.vid.aai.SubscriberFilteredResults; import org.openecomp.vid.aai.model.AaiGetTenatns.GetTenantsResponse; +import org.openecomp.vid.model.VersionByInvariantIdsRequest; import org.openecomp.vid.roles.Role; import org.openecomp.vid.roles.RoleProvider; import org.openecomp.vid.roles.RoleValidator; @@ -43,13 +44,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; - import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -70,859 +67,886 @@ import java.util.*; @RestController public class AaiController extends RestrictedBaseController { - - public AaiController() { - - } -public AaiController(ServletContext servletContext) { - this.servletContext = servletContext; - - } - - - - - /** - * The Constant dateFormat. - */ - final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); - /** - * The from app id. - */ - protected String fromAppId = "VidAaiController"; - /** - * The view name. - */ - String viewName; - /** - * The logger. - */ - EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AaiController.class); - - - /** - * The model. - */ - private Map model = new HashMap(); - /** - * The servlet context. - */ - @Autowired - private ServletContext servletContext; - - /** - * aai service - */ - @Autowired - private AaiService aaiService; - - - - /** - * Return tenant details. - * - * @param jsonObject the json object - * @return String The parsing results - */ - public static String parseCustomerObjectForTenants(JSONObject jsonObject) { - - JSONArray tenantArray = new JSONArray(); - boolean bconvert = false; - - try { - - JSONObject serviceSubsObj = (JSONObject) jsonObject.get("service-subscriptions"); - - if (serviceSubsObj != null) { - JSONArray srvcSubArray = (JSONArray) serviceSubsObj.get("service-subscription"); - - if (srvcSubArray != null) { - Iterator i = srvcSubArray.iterator(); - - while (i.hasNext()) { - - JSONObject innerObj = (JSONObject) i.next(); - - if (innerObj == null) - continue; - - JSONObject relationShipListsObj = (JSONObject) innerObj.get("relationship-list"); - if (relationShipListsObj != null) { - JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); - if (rShipArray != null) { - Iterator i1 = rShipArray.iterator(); - - while (i1.hasNext()) { - - JSONObject inner1Obj = (JSONObject) i1.next(); - - if (inner1Obj == null) - continue; - - String relatedTo = checkForNull((String) inner1Obj.get("related-to")); - if (relatedTo.equalsIgnoreCase("tenant")) { - JSONObject tenantNewObj = new JSONObject(); - - String relatedLink = checkForNull((String) inner1Obj.get("related-link")); - tenantNewObj.put("link", relatedLink); - - JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); - if (rDataArray != null) { - Iterator i2 = rDataArray.iterator(); - - while (i2.hasNext()) { - JSONObject inner2Obj = (JSONObject) i2.next(); - - if (inner2Obj == null) - continue; - - String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); - String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); - if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { - tenantNewObj.put("cloudOwner", rShipVal); - } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { - tenantNewObj.put("cloudRegionID", rShipVal); - } - - if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { - tenantNewObj.put("tenantID", rShipVal); - } - } - } - - JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); - if (relatedTPropArray != null) { - Iterator i3 = relatedTPropArray.iterator(); - - while (i3.hasNext()) { - JSONObject inner3Obj = (JSONObject) i3.next(); - - if (inner3Obj == null) - continue; - - String propKey = checkForNull((String) inner3Obj.get("property-key")); - String propVal = checkForNull((String) inner3Obj.get("property-value")); - if (propKey.equalsIgnoreCase("tenant.tenant-name")) { - tenantNewObj.put("tenantName", propVal); - } - } - } - bconvert = true; - tenantArray.add(tenantNewObj); - } - } - } - } - } - } - } - } catch (NullPointerException ex) { + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + /** + * The from app id. + */ + protected String fromAppId = "VidAaiController"; + /** + * The view name. + */ + String viewName; + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AaiController.class); + /** + * The model. + */ + private Map model = new HashMap(); + /** + * The servlet context. + */ + @Autowired + private ServletContext servletContext; + /** + * aai service + */ + @Autowired + private AaiService aaiService; + public AaiController() { + + } + + public AaiController(ServletContext servletContext) { + this.servletContext = servletContext; + + } + + /** + * Return tenant details. + * + * @param jsonObject the json object + * @return String The parsing results + */ + public static String parseCustomerObjectForTenants(JSONObject jsonObject) { + + JSONArray tenantArray = new JSONArray(); + boolean bconvert = false; + + try { + + JSONObject serviceSubsObj = (JSONObject) jsonObject.get("service-subscriptions"); + + if (serviceSubsObj != null) { + JSONArray srvcSubArray = (JSONArray) serviceSubsObj.get("service-subscription"); + + if (srvcSubArray != null) { + Iterator i = srvcSubArray.iterator(); + + while (i.hasNext()) { + + JSONObject innerObj = (JSONObject) i.next(); + + if (innerObj == null) + continue; + + JSONObject relationShipListsObj = (JSONObject) innerObj.get("relationship-list"); + if (relationShipListsObj != null) { + JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); + if (rShipArray != null) { + Iterator i1 = rShipArray.iterator(); + + while (i1.hasNext()) { + + JSONObject inner1Obj = (JSONObject) i1.next(); + + if (inner1Obj == null) + continue; + + String relatedTo = checkForNull((String) inner1Obj.get("related-to")); + if (relatedTo.equalsIgnoreCase("tenant")) { + JSONObject tenantNewObj = new JSONObject(); + + String relatedLink = checkForNull((String) inner1Obj.get("related-link")); + tenantNewObj.put("link", relatedLink); + + JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); + if (rDataArray != null) { + Iterator i2 = rDataArray.iterator(); + + while (i2.hasNext()) { + JSONObject inner2Obj = (JSONObject) i2.next(); + + if (inner2Obj == null) + continue; + + String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); + String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); + if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { + tenantNewObj.put("cloudOwner", rShipVal); + } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { + tenantNewObj.put("cloudRegionID", rShipVal); + } + + if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { + tenantNewObj.put("tenantID", rShipVal); + } + } + } + + JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); + if (relatedTPropArray != null) { + Iterator i3 = relatedTPropArray.iterator(); + + while (i3.hasNext()) { + JSONObject inner3Obj = (JSONObject) i3.next(); + + if (inner3Obj == null) + continue; + + String propKey = checkForNull((String) inner3Obj.get("property-key")); + String propVal = checkForNull((String) inner3Obj.get("property-value")); + if (propKey.equalsIgnoreCase("tenant.tenant-name")) { + tenantNewObj.put("tenantName", propVal); + } + } + } + bconvert = true; + tenantArray.add(tenantNewObj); + } + } + } + } + } + } + } + } catch (NullPointerException ex) { - } - if (bconvert) - return tenantArray.toJSONString(); - else - return ""; + } - } + if (bconvert) + return tenantArray.toJSONString(); + else + return ""; + } - /** - * Retrieve the service subscription from the jsonObject. - * - * @param jsonObject the json object - * @return String - */ - public static String parseServiceSubscriptionObjectForTenants(JSONObject jsonObject) { - - JSONArray tenantArray = new JSONArray(); - boolean bconvert = false; - - try { - JSONObject relationShipListsObj = (JSONObject) jsonObject.get("relationship-list"); - if (relationShipListsObj != null) { - JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); - if (rShipArray != null) { - Iterator i1 = rShipArray.iterator(); - - while (i1.hasNext()) { - - JSONObject inner1Obj = (JSONObject) i1.next(); - - if (inner1Obj == null) - continue; - - String relatedTo = checkForNull((String) inner1Obj.get("related-to")); - if (relatedTo.equalsIgnoreCase("tenant")) { - JSONObject tenantNewObj = new JSONObject(); - - String relatedLink = checkForNull((String) inner1Obj.get("related-link")); - tenantNewObj.put("link", relatedLink); - - JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); - if (rDataArray != null) { - Iterator i2 = rDataArray.iterator(); - - while (i2.hasNext()) { - JSONObject inner2Obj = (JSONObject) i2.next(); - - if (inner2Obj == null) - continue; - - String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); - String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); - if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { - tenantNewObj.put("cloudOwner", rShipVal); - } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { - tenantNewObj.put("cloudRegionID", rShipVal); - } - - if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { - tenantNewObj.put("tenantID", rShipVal); - } - } - } - - JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); - if (relatedTPropArray != null) { - Iterator i3 = relatedTPropArray.iterator(); - - while (i3.hasNext()) { - JSONObject inner3Obj = (JSONObject) i3.next(); - - if (inner3Obj == null) - continue; - - String propKey = checkForNull((String) inner3Obj.get("property-key")); - String propVal = checkForNull((String) inner3Obj.get("property-value")); - if (propKey.equalsIgnoreCase("tenant.tenant-name")) { - tenantNewObj.put("tenantName", propVal); - } - } - } - bconvert = true; - tenantArray.add(tenantNewObj); - } - } - - } - } - } catch (NullPointerException ex) { - - - } - - if (bconvert) - return tenantArray.toJSONString(); - else - return ""; - - } - - /** - * Check for null. - * - * @param local the local - * @return the string - */ - private static String checkForNull(String local) { - if (local != null) - return local; - else - return ""; - - } - - /** - * Welcome method. - * - * @param request the request - * @return ModelAndView The view - */ - @RequestMapping(value = {"/subscriberSearch"}, method = RequestMethod.GET) - public ModelAndView welcome(HttpServletRequest request) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== AaiController welcome start"); - return new ModelAndView(getViewName()); - } - - @RequestMapping(value = {"/aai_get_aic_zones"}, method = RequestMethod.GET) - public ResponseEntity getAicZones(HttpServletRequest request) throws JsonGenerationException, JsonMappingException, IOException { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== getAicZones controller start"); - AaiResponse response = aaiService.getAaiZones(); - return aaiResponseToResponseEntity(response); - - } - - /* (non-Javadoc) - * @see org.openecomp.portalsdk.core.controller.RestrictedBaseController#getViewName() - */ - public String getViewName() { - return viewName; - } - - /* (non-Javadoc) - * @see org.openecomp.portalsdk.core.controller.RestrictedBaseController#setViewName(java.lang.String) - */ - public void setViewName(String viewName) { - this.viewName = viewName; - } - - /** - * Get services from a&ai. - * - * @return ResponseEntity The response entity with the logged in user uuid. - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = {"/getuserID"}, method = RequestMethod.GET) - public ResponseEntity getUserID(HttpServletRequest request) throws IOException, InterruptedException { - - String userId = ""; - HttpSession session = request.getSession(); - if (session != null) { - User user = (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME)); - if (user != null) { - //userId = user.getHrid(); - userId = user.getLoginId(); - if (userId == null) - userId = user.getOrgUserId(); - } - } - - return new ResponseEntity(userId, HttpStatus.OK); - } - - /** - * Get services from a&ai. - * - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/aai_get_services", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doGetServices(HttpServletRequest request) throws IOException, InterruptedException { - - RoleValidator roleValidator = new RoleValidator(new RoleProvider().getUserRoles(request)); - - AaiResponse subscriberList = aaiService.getServices(roleValidator); - ResponseEntity responseEntity = aaiResponseToResponseEntity( subscriberList); - - return responseEntity; - } - - - - private ResponseEntity aaiResponseToResponseEntity( AaiResponse aaiResponseData) - throws IOException, JsonGenerationException, JsonMappingException { - ResponseEntity responseEntity; - ObjectMapper objectMapper = new ObjectMapper(); - if (aaiResponseData.getHttpCode() == 200) { - responseEntity = new ResponseEntity(objectMapper.writeValueAsString(aaiResponseData.getT()), HttpStatus.OK); - } else { - responseEntity = new ResponseEntity(aaiResponseData.getErrorMessage(), HttpStatus.valueOf(aaiResponseData.getHttpCode())); - } - return responseEntity; - } - - /** - * Lookup single service instance in a&ai. Get the service-subscription and customer, too, i guess? - * - * @param serviceInstanceId the service instance Id - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/aai_get_service_instance/{service-instance-id}/{service-instance-type}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doGetServiceInstance(@PathVariable("service-instance-id") String serviceInstanceId, @PathVariable("service-instance-type") String serviceInstanceType) throws IOException, InterruptedException { - File certiPath = GetCertificatesPath(); - Response resp = null; - - if (serviceInstanceType.equalsIgnoreCase("Service Instance Id")) { - resp = doAaiGet(certiPath.getAbsolutePath(), - "search/nodes-query?search-node-type=service-instance&filter=service-instance-id:EQUALS:" - + serviceInstanceId, false); - } else { - resp = doAaiGet(certiPath.getAbsolutePath(), - "search/nodes-query?search-node-type=service-instance&filter=service-instance-name:EQUALS:" - + serviceInstanceId, false); - } - return convertResponseToResponseEntity(resp); - } - - /** - * Get services from a&ai. - * - * @param globalCustomerId the global customer id - * @param serviceSubscriptionId the service subscription id - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/aai_get_service_subscription/{global-customer-id}/{service-subscription-id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doGetServices(@PathVariable("global-customer-id") String globalCustomerId, - @PathVariable("service-subscription-id") String serviceSubscriptionId) throws IOException, InterruptedException { - File certiPath = GetCertificatesPath(); - Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + globalCustomerId - + "/service-subscriptions/service-subscription/" + serviceSubscriptionId + "?depth=0", false); - return convertResponseToResponseEntity(resp); - } - - /** - * Obtain the subscriber list from a&ai. - * - * @param fullSet the full set - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/aai_get_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doGetSubscriberList(HttpServletRequest request,@DefaultValue("n") @QueryParam("fullSet") String fullSet) throws IOException, InterruptedException { - return getFullSubscriberList(request); - } - - /** - * Obtain the Target Prov Status from the System.Properties file. - * - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/get_system_prop_vnf_prov_status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getTargetProvStatus() throws IOException, InterruptedException { - String p = SystemProperties.getProperty("aai.vnf.provstatus"); - return new ResponseEntity(p, HttpStatus.OK); - } - - /** - * Obtain the full subscriber list from a&ai. - *

- * g @return ResponseEntity The response entity - * - * @throws IOException Signals that an I/O exception has occurred. - * @throws InterruptedException the interrupted exception - */ - @RequestMapping(value = "/aai_get_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getFullSubscriberList(HttpServletRequest request) throws IOException, InterruptedException { - ObjectMapper objectMapper = new ObjectMapper(); - ResponseEntity responseEntity; - RoleValidator roleValidator = new RoleValidator(new RoleProvider().getUserRoles(request)); - SubscriberFilteredResults subscriberList = aaiService.getFullSubscriberList(roleValidator); - if (subscriberList.getHttpCode() == 200) { - responseEntity = new ResponseEntity(objectMapper.writeValueAsString(subscriberList.getSubscriberList()), HttpStatus.OK); - } else { - responseEntity = new ResponseEntity(subscriberList.getErrorMessage(), HttpStatus.valueOf(subscriberList.getHttpCode())); - } - - - return responseEntity; - } - - /** - * Refresh the subscriber list from a&ai. - * - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - */ - @RequestMapping(value = "/aai_refresh_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doRefreshSubscriberList() throws IOException { - Response resp = getSubscribers(false); - return convertResponseToResponseEntity(resp); - } - - /** - * Refresh the full subscriber list from a&ai. - * - * @return ResponseEntity The response entity - * @throws IOException Signals that an I/O exception has occurred. - */ - @RequestMapping(value = "/aai_refresh_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity doRefreshFullSubscriberList() throws IOException { - Response resp = getSubscribers(false); - return convertResponseToResponseEntity(resp); - } - - /** - * Get subscriber details from a&ai. - * - * @param subscriberId the subscriber id - * @return ResponseEntity The response entity - */ - @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET) - public ResponseEntity GetSubscriberDetails(HttpServletRequest request,@PathVariable("subscriberId") String subscriberId) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - ResponseEntity responseEntity; - List roles = new RoleProvider().getUserRoles(request); - RoleValidator roleValidator = new RoleValidator(roles); - AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId,roleValidator); - String httpMessage = subscriberData.getT() != null ? - objectMapper.writeValueAsString(subscriberData.getT()) : - subscriberData.getErrorMessage(); - - responseEntity = new ResponseEntity(httpMessage, HttpStatus.valueOf(subscriberData.getHttpCode())); - return responseEntity; - } - - /** - * Issue a named query to a&ai. - * - * @param namedQueryId the named query id - * @param globalCustomerId the global customer id - * @param serviceType the service type - * @param serviceInstance the service instance - * @return ResponseEntity The response entity - */ - @RequestMapping(value = "/aai_sub_viewedit/{namedQueryId}/{globalCustomerId}/{serviceType}/{serviceInstance}", method = RequestMethod.GET) - public ResponseEntity viewEditGetComponentList( - @PathVariable("namedQueryId") String namedQueryId, - @PathVariable("globalCustomerId") String globalCustomerId, - @PathVariable("serviceType") String serviceType, - @PathVariable("serviceInstance") String serviceInstance) { - - String componentListPayload = getComponentListPutPayload(namedQueryId, globalCustomerId, serviceType, serviceInstance); - File certiPath = GetCertificatesPath(); - - Response resp = doAaiPost(certiPath.getAbsolutePath(), "search/named-query", componentListPayload, false); - return convertResponseToResponseEntity(resp); - } - - - // @RequestMapping(value="/aai_get_tenants/{global-customer-id}", method = RequestMethod.GET) - // public ResponseEntity viewEditGetComponentList( - // @PathVariable("global-customer-id") String globalCustomerId) { - // return new ResponseEntity(getTenants(globalCustomerId), HttpStatus.OK); - // } - - /** - * Issue a named query to a&ai. - * - * @param namedQueryId the named query id - * @param globalCustomerId the global customer id - * @param serviceType the service type - * @return ResponseEntity The response entity - */ - @RequestMapping(value = "/aai_get_models_by_service_type/{namedQueryId}/{globalCustomerId}/{serviceType}", method = RequestMethod.GET) - public ResponseEntity viewEditGetComponentList( - @PathVariable("namedQueryId") String namedQueryId, - @PathVariable("globalCustomerId") String globalCustomerId, - @PathVariable("serviceType") String serviceType) { - - String componentListPayload = getModelsByServiceTypePayload(namedQueryId, globalCustomerId, serviceType); - File certiPath = GetCertificatesPath(); - - Response resp = doAaiPost(certiPath.getAbsolutePath(), "search/named-query", componentListPayload, false); - return convertResponseToResponseEntity(resp); - } - - /** - * Parses the for tenants. - * - * @param resp the resp - * @return the string - */ - private String parseForTenants(String resp) { - String tenantList = ""; - - try { - JSONParser jsonParser = new JSONParser(); - - JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); - - return parseCustomerObjectForTenants(jsonObject); - } catch (Exception ex) { - - } - - return tenantList; - } - - /** - * Parses the for tenants by service subscription. - * - * @param resp the resp - * @return the string - */ - private String parseForTenantsByServiceSubscription(String resp) { - String tenantList = ""; - - try { - JSONParser jsonParser = new JSONParser(); - - JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); - - return parseServiceSubscriptionObjectForTenants(jsonObject); - } catch (Exception ex) { - - } - - return tenantList; - } - - /** - * Obtain tenants for a given service type. - * - * @param globalCustomerId the global customer id - * @param serviceType the service type - * @return ResponseEntity The response entity - */ - @RequestMapping(value = "/aai_get_tenants/{global-customer-id}/{service-type}", method = RequestMethod.GET) - public ResponseEntity viewEditGetTenantsFromServiceType(HttpServletRequest request, - @PathVariable("global-customer-id") String globalCustomerId, @PathVariable("service-type") String serviceType) { - - ResponseEntity responseEntity; - try { - ObjectMapper objectMapper = new ObjectMapper(); - List roles = new RoleProvider().getUserRoles(request); - RoleValidator roleValidator = new RoleValidator(roles); - AaiResponse response = aaiService.getTenants(globalCustomerId, serviceType, roleValidator); - if (response.getHttpCode() == 200) { - responseEntity = new ResponseEntity(objectMapper.writeValueAsString(response.getT()), HttpStatus.OK); - } else { - responseEntity = new ResponseEntity(response.getErrorMessage(), HttpStatus.valueOf(response.getHttpCode())); - } - } - catch (Exception e){ - responseEntity = new ResponseEntity("Unable to proccess getTenants reponse", HttpStatus.INTERNAL_SERVER_ERROR); - } - return responseEntity; - } - - - private ResponseEntity convertResponseToResponseEntity(Response resp) { - ResponseEntity respEnt; - ObjectMapper objectMapper = new ObjectMapper(); - if (resp == null) { - respEnt = new ResponseEntity("Failed to fetch data from A&AI, check server logs for details.", HttpStatus.INTERNAL_SERVER_ERROR); - } else { - respEnt = new ResponseEntity(resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); - } - return respEnt; - } - - /** - * Gets the tenants. - * - * @param globalCustomerId the global customer id - * @return the tenants - */ - private ResponseEntity getTenants(String globalCustomerId) { - File certiPath = GetCertificatesPath(); - Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + globalCustomerId, false); - - ResponseEntity respEnt; - if (resp.getStatus() >= 200 && resp.getStatus() <= 299) { - respEnt = new ResponseEntity(parseForTenants((String) resp.readEntity(String.class)), HttpStatus.OK); - } else { - respEnt = new ResponseEntity((String) resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); - } - return respEnt; - - } - - /** - * Gets the tenants from service type. - * - * @param globalCustomerId the global customer id - * @param serviceType the service type - * @return the tenants from service type - */ - private ResponseEntity getTenantsFromServiceType(String globalCustomerId, String serviceType) { - - - - - - File certiPath = GetCertificatesPath(); - String url = "business/customers/customer/" + globalCustomerId + "/service-subscriptions/service-subscription/" + serviceType; - - Response resp = doAaiGet(certiPath.getAbsolutePath(), url, false); - - ResponseEntity respEnt; - if (resp.getStatus() >= 200 && resp.getStatus() <= 299) { - respEnt = new ResponseEntity(parseForTenantsByServiceSubscription((String) resp.readEntity(String.class)), HttpStatus.OK); - } else { - respEnt = new ResponseEntity((String) resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); - } - return respEnt; - - } - - /** - * Gets the services. - * - * @return the services - */ - private Response getServices() { - File certiPath = GetCertificatesPath(); - Response resp = doAaiGet(certiPath.getAbsolutePath(), "service-design-and-creation/services", false); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getServices() resp=" + resp.getStatusInfo()); - - //model.put("aai_get_services", resp); - return resp; - } - - /** - * Gets the subscribers. - * - * @param isFullSet the is full set - * @return the subscribers - */ - private Response getSubscribers(boolean isFullSet) { - - File certiPath = GetCertificatesPath(); - String depth = "0"; - - Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers?subscriber-type=INFRA&depth=" + depth, false); - if (resp != null) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscribers() resp=" + resp.getStatusInfo().toString()); - } - return resp; - } - - /** - * Gets the subscriber details. - * - * @param subscriberId the subscriber id - * @return the subscriber details - */ - private Response getSubscriberDetails(String subscriberId) { - File certiPath = GetCertificatesPath(); - Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId + "?depth=2", false); - //String resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId, false); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscriberDetails() resp=" + resp.getStatusInfo().toString()); - return resp; - } - - /** - * Gets the certificates path. - * - * @return the file - */ - private File GetCertificatesPath() { - if (servletContext != null) - return new File(servletContext.getRealPath("/WEB-INF/cert/")); - return null; - } - - /** - * Send a GET request to a&ai. - * - * @param certiPath the certi path - * @param uri the uri - * @param xml the xml - * @return String The response - */ - protected Response doAaiGet(String certiPath, String uri, boolean xml) { - String methodName = "getSubscriberList"; - String transId = UUID.randomUUID().toString(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - - Response resp = null; - try { - - AAIRestInterface restContrller = new AAIRestInterface(certiPath); - resp = restContrller.RestGet(fromAppId, transId, uri, xml); - - } catch (WebApplicationException e) { - final String message = ((BadRequestException) e).getResponse().readEntity(String.class); - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - } - - return resp; - } - - /** - * Send a POST request to a&ai. - * - * @param certiPath the certi path - * @param uri the uri - * @param payload the payload - * @param xml the xml - * @return String The response - */ - protected Response doAaiPost(String certiPath, String uri, String payload, boolean xml) { - String methodName = "getSubscriberList"; - String transId = UUID.randomUUID().toString(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - - Response resp = null; - try { - - AAIRestInterface restContrller = new AAIRestInterface(certiPath); - resp = restContrller.RestPost(fromAppId, transId, uri, payload, xml); - - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - } - - return resp; - } - - /** - * Gets the component list put payload. - * - * @param namedQueryId the named query id - * @param globalCustomerId the global customer id - * @param serviceType the service type - * @param serviceInstance the service instance - * @return the component list put payload - */ - private String getComponentListPutPayload(String namedQueryId, String globalCustomerId, String serviceType, String serviceInstance) { - return - " {" + - " \"instance-filters\": {" + - " \"instance-filter\": [" + - " {" + - " \"customer\": {" + - " \"global-customer-id\": \"" + globalCustomerId + "\"" + - " }," + - " \"service-instance\": {" + - " \"service-instance-id\": \"" + serviceInstance + "\"" + - " }," + - " \"service-subscription\": {" + - " \"service-type\": \"" + serviceType + "\"" + - " }" + - " }" + - " ]" + - " }," + - " \"query-parameters\": {" + - " \"named-query\": {" + - " \"named-query-uuid\": \"" + namedQueryId + "\"" + - " }" + - " }" + - "}"; - - } - - private String getModelsByServiceTypePayload(String namedQueryId, String globalCustomerId, String serviceType) { - // TODO Auto-generated method stub - return " {" + - " \"instance-filters\": {" + - " \"instance-filter\": [" + - " {" + - " \"customer\": {" + - " \"global-customer-id\": \"" + globalCustomerId + "\"" + - " }," + - " \"service-subscription\": {" + - " \"service-type\": \"" + serviceType + "\"" + - " }" + - " }" + - " ]" + - " }," + - " \"query-parameters\": {" + - " \"named-query\": {" + - " \"named-query-uuid\": \"" + namedQueryId + "\"" + - " }" + - " }" + - "}"; - - } + /** + * Retrieve the service subscription from the jsonObject. + * + * @param jsonObject the json object + * @return String + */ + public static String parseServiceSubscriptionObjectForTenants(JSONObject jsonObject) { + + JSONArray tenantArray = new JSONArray(); + boolean bconvert = false; + + try { + JSONObject relationShipListsObj = (JSONObject) jsonObject.get("relationship-list"); + if (relationShipListsObj != null) { + JSONArray rShipArray = (JSONArray) relationShipListsObj.get("relationship"); + if (rShipArray != null) { + Iterator i1 = rShipArray.iterator(); + + while (i1.hasNext()) { + + JSONObject inner1Obj = (JSONObject) i1.next(); + + if (inner1Obj == null) + continue; + + String relatedTo = checkForNull((String) inner1Obj.get("related-to")); + if (relatedTo.equalsIgnoreCase("tenant")) { + JSONObject tenantNewObj = new JSONObject(); + + String relatedLink = checkForNull((String) inner1Obj.get("related-link")); + tenantNewObj.put("link", relatedLink); + + JSONArray rDataArray = (JSONArray) inner1Obj.get("relationship-data"); + if (rDataArray != null) { + Iterator i2 = rDataArray.iterator(); + + while (i2.hasNext()) { + JSONObject inner2Obj = (JSONObject) i2.next(); + + if (inner2Obj == null) + continue; + + String rShipKey = checkForNull((String) inner2Obj.get("relationship-key")); + String rShipVal = checkForNull((String) inner2Obj.get("relationship-value")); + if (rShipKey.equalsIgnoreCase("cloud-region.cloud-owner")) { + tenantNewObj.put("cloudOwner", rShipVal); + } else if (rShipKey.equalsIgnoreCase("cloud-region.cloud-region-id")) { + tenantNewObj.put("cloudRegionID", rShipVal); + } + + if (rShipKey.equalsIgnoreCase("tenant.tenant-id")) { + tenantNewObj.put("tenantID", rShipVal); + } + } + } + + JSONArray relatedTPropArray = (JSONArray) inner1Obj.get("related-to-property"); + if (relatedTPropArray != null) { + Iterator i3 = relatedTPropArray.iterator(); + + while (i3.hasNext()) { + JSONObject inner3Obj = (JSONObject) i3.next(); + + if (inner3Obj == null) + continue; + + String propKey = checkForNull((String) inner3Obj.get("property-key")); + String propVal = checkForNull((String) inner3Obj.get("property-value")); + if (propKey.equalsIgnoreCase("tenant.tenant-name")) { + tenantNewObj.put("tenantName", propVal); + } + } + } + bconvert = true; + tenantArray.add(tenantNewObj); + } + } + + } + } + } catch (NullPointerException ex) { + + + } + + if (bconvert) + return tenantArray.toJSONString(); + else + return ""; + + } + + /** + * Check for null. + * + * @param local the local + * @return the string + */ + private static String checkForNull(String local) { + if (local != null) + return local; + else + return ""; + + } + + /** + * Welcome method. + * + * @param request the request + * @return ModelAndView The view + */ + @RequestMapping(value = {"/subscriberSearch"}, method = RequestMethod.GET) + public ModelAndView welcome(HttpServletRequest request) { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== AaiController welcome start"); + return new ModelAndView(getViewName()); + } + + @RequestMapping(value = {"/aai_get_aic_zones"}, method = RequestMethod.GET) + public ResponseEntity getAicZones(HttpServletRequest request) throws JsonGenerationException, JsonMappingException, IOException { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== getAicZones controller start"); + AaiResponse response = aaiService.getAaiZones(); + return aaiResponseToResponseEntity(response); + } + + @RequestMapping(value = {"/aai_get_aic_zone_for_pnf/{globalCustomerId}/{serviceType}/{serviceId}"}, method = RequestMethod.GET) + public ResponseEntity getAicZoneForPnf(@PathVariable("globalCustomerId") String globalCustomerId ,@PathVariable("serviceType") String serviceType , @PathVariable("serviceId") String serviceId ,HttpServletRequest request) throws JsonGenerationException, JsonMappingException, IOException { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== getAicZoneForPnf controller start"); + AaiResponse response = aaiService.getAicZoneForPnf(globalCustomerId , serviceType , serviceId); + return aaiResponseToResponseEntity(response); + } + + /* (non-Javadoc) + * @see org.openecomp.portalsdk.core.controller.RestrictedBaseController#getViewName() + */ + public String getViewName() { + return viewName; + } + + /* (non-Javadoc) + * @see org.openecomp.portalsdk.core.controller.RestrictedBaseController#setViewName(java.lang.String) + */ + public void setViewName(String viewName) { + this.viewName = viewName; + } + + /** + * Get services from a&ai. + * + * @return ResponseEntity The response entity with the logged in user uuid. + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = {"/getuserID"}, method = RequestMethod.GET) + public ResponseEntity getUserID(HttpServletRequest request) throws IOException, InterruptedException { + + String userId = ""; + HttpSession session = request.getSession(); + if (session != null) { + User user = (User) session.getAttribute(SystemProperties.getProperty(SystemProperties.USER_ATTRIBUTE_NAME)); + if (user != null) { + //userId = user.getHrid(); + userId = user.getLoginId(); + if (userId == null) + userId = user.getOrgUserId(); + } + } + + return new ResponseEntity(userId, HttpStatus.OK); + } + + /** + * Get services from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/aai_get_services", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServices(HttpServletRequest request) throws IOException, InterruptedException { + + RoleValidator roleValidator = new RoleValidator(new RoleProvider().getUserRoles(request)); + + AaiResponse subscriberList = aaiService.getServices(roleValidator); + ResponseEntity responseEntity = aaiResponseToResponseEntity(subscriberList); + + return responseEntity; + } + + + @RequestMapping(value = {"/aai_get_version_by_invariant_id"}, method = RequestMethod.POST) + public ResponseEntity getVersionByInvariantId(HttpServletRequest request, @RequestBody VersionByInvariantIdsRequest versions) throws IOException { + ResponseEntity responseEntity; + ObjectMapper objectMapper = new ObjectMapper(); + + Response result = aaiService.getVersionByInvariantId(versions.versions); + + return new ResponseEntity(result.readEntity(String.class), HttpStatus.OK); + } + + + private ResponseEntity aaiResponseToResponseEntity(AaiResponse aaiResponseData) + throws IOException, JsonGenerationException, JsonMappingException { + ResponseEntity responseEntity; + ObjectMapper objectMapper = new ObjectMapper(); + if (aaiResponseData.getHttpCode() == 200) { + responseEntity = new ResponseEntity(objectMapper.writeValueAsString(aaiResponseData.getT()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity(aaiResponseData.getErrorMessage(), HttpStatus.valueOf(aaiResponseData.getHttpCode())); + } + return responseEntity; + } + + /** + * Lookup single service instance in a&ai. Get the service-subscription and customer, too, i guess? + * + * @param serviceInstanceId the service instance Id + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/aai_get_service_instance/{service-instance-id}/{service-instance-type}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServiceInstance(@PathVariable("service-instance-id") String serviceInstanceId, @PathVariable("service-instance-type") String serviceInstanceType) throws IOException, InterruptedException { + File certiPath = GetCertificatesPath(); + Response resp = null; + + if (serviceInstanceType.equalsIgnoreCase("Service Instance Id")) { + resp = doAaiGet(certiPath.getAbsolutePath(), + "search/nodes-query?search-node-type=service-instance&filter=service-instance-id:EQUALS:" + + serviceInstanceId, false); + } else { + resp = doAaiGet(certiPath.getAbsolutePath(), + "search/nodes-query?search-node-type=service-instance&filter=service-instance-name:EQUALS:" + + serviceInstanceId, false); + } + return convertResponseToResponseEntity(resp); + } + + /** + * Get services from a&ai. + * + * @param globalCustomerId the global customer id + * @param serviceSubscriptionId the service subscription id + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/aai_get_service_subscription/{global-customer-id}/{service-subscription-id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetServices(@PathVariable("global-customer-id") String globalCustomerId, + @PathVariable("service-subscription-id") String serviceSubscriptionId) throws IOException, InterruptedException { + File certiPath = GetCertificatesPath(); + Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + globalCustomerId + + "/service-subscriptions/service-subscription/" + serviceSubscriptionId + "?depth=0", false); + return convertResponseToResponseEntity(resp); + } + + /** + * Obtain the subscriber list from a&ai. + * + * @param fullSet the full set + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/aai_get_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doGetSubscriberList(HttpServletRequest request, @DefaultValue("n") @QueryParam("fullSet") String fullSet) throws IOException, InterruptedException { + return getFullSubscriberList(request); + } + + /** + * Obtain the Target Prov Status from the System.Properties file. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/get_system_prop_vnf_prov_status", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getTargetProvStatus() throws IOException, InterruptedException { + String p = SystemProperties.getProperty("aai.vnf.provstatus"); + return new ResponseEntity(p, HttpStatus.OK); + } + + /** + * Obtain the full subscriber list from a&ai. + *

+ * g @return ResponseEntity The response entity + * + * @throws IOException Signals that an I/O exception has occurred. + * @throws InterruptedException the interrupted exception + */ + @RequestMapping(value = "/aai_get_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getFullSubscriberList(HttpServletRequest request) throws IOException, InterruptedException { + ObjectMapper objectMapper = new ObjectMapper(); + ResponseEntity responseEntity; + RoleValidator roleValidator = new RoleValidator(new RoleProvider().getUserRoles(request)); + SubscriberFilteredResults subscriberList = aaiService.getFullSubscriberList(roleValidator); + if (subscriberList.getHttpCode() == 200) { + responseEntity = new ResponseEntity(objectMapper.writeValueAsString(subscriberList.getSubscriberList()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity(subscriberList.getErrorMessage(), HttpStatus.valueOf(subscriberList.getHttpCode())); + } + + + return responseEntity; + } + + + @RequestMapping(value = "/get_vnf_data_by_globalid_and_service_type/{globalCustomerId}/{serviceType}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getVnfDataByGlobalIdAndServiceType(HttpServletRequest request, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType) throws IOException { + + Response resp = aaiService.getVNFData(globalCustomerId, serviceType); + return convertResponseToResponseEntity(resp); + } + + + /** + * Refresh the subscriber list from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_refresh_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doRefreshSubscriberList() throws IOException { + Response resp = getSubscribers(false); + return convertResponseToResponseEntity(resp); + } + + /** + * Refresh the full subscriber list from a&ai. + * + * @return ResponseEntity The response entity + * @throws IOException Signals that an I/O exception has occurred. + */ + @RequestMapping(value = "/aai_refresh_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doRefreshFullSubscriberList() throws IOException { + Response resp = getSubscribers(false); + return convertResponseToResponseEntity(resp); + } + + /** + * Get subscriber details from a&ai. + * + * @param subscriberId the subscriber id + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET) + public ResponseEntity GetSubscriberDetails(HttpServletRequest request, @PathVariable("subscriberId") String subscriberId) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ResponseEntity responseEntity; + List roles = new RoleProvider().getUserRoles(request); + RoleValidator roleValidator = new RoleValidator(roles); + AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator); + String httpMessage = subscriberData.getT() != null ? + objectMapper.writeValueAsString(subscriberData.getT()) : + subscriberData.getErrorMessage(); + + responseEntity = new ResponseEntity(httpMessage, HttpStatus.valueOf(subscriberData.getHttpCode())); + return responseEntity; + } + + /** + * Issue a named query to a&ai. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @param serviceInstance the service instance + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_sub_viewedit/{namedQueryId}/{globalCustomerId}/{serviceType}/{serviceInstance}", method = RequestMethod.GET) + public ResponseEntity viewEditGetComponentList( + @PathVariable("namedQueryId") String namedQueryId, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("serviceInstance") String serviceInstance) { + + String componentListPayload = getComponentListPutPayload(namedQueryId, globalCustomerId, serviceType, serviceInstance); + File certiPath = GetCertificatesPath(); + + Response resp = doAaiPost(certiPath.getAbsolutePath(), "search/named-query", componentListPayload, false); + return convertResponseToResponseEntity(resp); + } + + + @RequestMapping(value = "/aai_get_vnf_data/{globalCustomerId}/{serviceType}/{serviceInstanceId}", method = RequestMethod.GET) + public AaiResponse getVnfData( + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType, + @PathVariable("serviceInstanceId") String serviceInstanceId) { + + return aaiService.getVNFData(globalCustomerId, serviceType, serviceInstanceId); + + } + + + // @RequestMapping(value="/aai_get_tenants/{global-customer-id}", method = RequestMethod.GET) + // public ResponseEntity viewEditGetComponentList( + // @PathVariable("global-customer-id") String globalCustomerId) { + // return new ResponseEntity(getTenants(globalCustomerId), HttpStatus.OK); + // } + + /** + * Issue a named query to a&ai. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_get_models_by_service_type/{namedQueryId}/{globalCustomerId}/{serviceType}", method = RequestMethod.GET) + public ResponseEntity viewEditGetComponentList( + @PathVariable("namedQueryId") String namedQueryId, + @PathVariable("globalCustomerId") String globalCustomerId, + @PathVariable("serviceType") String serviceType) { + + String componentListPayload = getModelsByServiceTypePayload(namedQueryId, globalCustomerId, serviceType); + File certiPath = GetCertificatesPath(); + + Response resp = doAaiPost(certiPath.getAbsolutePath(), "search/named-query", componentListPayload, false); + return convertResponseToResponseEntity(resp); + } + + /** + * Parses the for tenants. + * + * @param resp the resp + * @return the string + */ + private String parseForTenants(String resp) { + String tenantList = ""; + + try { + JSONParser jsonParser = new JSONParser(); + + JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); + + return parseCustomerObjectForTenants(jsonObject); + } catch (Exception ex) { + + } + + return tenantList; + } + + /** + * Parses the for tenants by service subscription. + * + * @param resp the resp + * @return the string + */ + private String parseForTenantsByServiceSubscription(String resp) { + String tenantList = ""; + + try { + JSONParser jsonParser = new JSONParser(); + + JSONObject jsonObject = (JSONObject) jsonParser.parse(resp); + + return parseServiceSubscriptionObjectForTenants(jsonObject); + } catch (Exception ex) { + + } + + return tenantList; + } + + /** + * Obtain tenants for a given service type. + * + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @return ResponseEntity The response entity + */ + @RequestMapping(value = "/aai_get_tenants/{global-customer-id}/{service-type}", method = RequestMethod.GET) + public ResponseEntity viewEditGetTenantsFromServiceType(HttpServletRequest request, + @PathVariable("global-customer-id") String globalCustomerId, @PathVariable("service-type") String serviceType) { + + ResponseEntity responseEntity; + try { + ObjectMapper objectMapper = new ObjectMapper(); + List roles = new RoleProvider().getUserRoles(request); + RoleValidator roleValidator = new RoleValidator(roles); + AaiResponse response = aaiService.getTenants(globalCustomerId, serviceType, roleValidator); + if (response.getHttpCode() == 200) { + responseEntity = new ResponseEntity(objectMapper.writeValueAsString(response.getT()), HttpStatus.OK); + } else { + responseEntity = new ResponseEntity(response.getErrorMessage(), HttpStatus.valueOf(response.getHttpCode())); + } + } catch (Exception e) { + responseEntity = new ResponseEntity("Unable to proccess getTenants reponse", HttpStatus.INTERNAL_SERVER_ERROR); + } + return responseEntity; + } + + + private ResponseEntity convertResponseToResponseEntity(Response resp) { + ResponseEntity respEnt; + ObjectMapper objectMapper = new ObjectMapper(); + if (resp == null) { + respEnt = new ResponseEntity("Failed to fetch data from A&AI, check server logs for details.", HttpStatus.INTERNAL_SERVER_ERROR); + } else { + respEnt = new ResponseEntity(resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); + } + return respEnt; + } + + /** + * Gets the tenants. + * + * @param globalCustomerId the global customer id + * @return the tenants + */ + private ResponseEntity getTenants(String globalCustomerId) { + File certiPath = GetCertificatesPath(); + Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + globalCustomerId, false); + + ResponseEntity respEnt; + if (resp.getStatus() >= 200 && resp.getStatus() <= 299) { + respEnt = new ResponseEntity(parseForTenants((String) resp.readEntity(String.class)), HttpStatus.OK); + } else { + respEnt = new ResponseEntity((String) resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); + } + return respEnt; + + } + + /** + * Gets the tenants from service type. + * + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @return the tenants from service type + */ + private ResponseEntity getTenantsFromServiceType(String globalCustomerId, String serviceType) { + + + File certiPath = GetCertificatesPath(); + String url = "business/customers/customer/" + globalCustomerId + "/service-subscriptions/service-subscription/" + serviceType; + + Response resp = doAaiGet(certiPath.getAbsolutePath(), url, false); + + ResponseEntity respEnt; + if (resp.getStatus() >= 200 && resp.getStatus() <= 299) { + respEnt = new ResponseEntity(parseForTenantsByServiceSubscription((String) resp.readEntity(String.class)), HttpStatus.OK); + } else { + respEnt = new ResponseEntity((String) resp.readEntity(String.class), HttpStatus.valueOf(resp.getStatus())); + } + return respEnt; + + } + + /** + * Gets the services. + * + * @return the services + */ + private Response getServices() { + File certiPath = GetCertificatesPath(); + Response resp = doAaiGet(certiPath.getAbsolutePath(), "service-design-and-creation/services", false); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getServices() resp=" + resp.getStatusInfo()); + + //model.put("aai_get_services", resp); + return resp; + } + + /** + * Gets the subscribers. + * + * @param isFullSet the is full set + * @return the subscribers + */ + private Response getSubscribers(boolean isFullSet) { + + File certiPath = GetCertificatesPath(); + String depth = "0"; + + Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers?subscriber-type=INFRA&depth=" + depth, false); + if (resp != null) { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscribers() resp=" + resp.getStatusInfo().toString()); + } + return resp; + } + + /** + * Gets the subscriber details. + * + * @param subscriberId the subscriber id + * @return the subscriber details + */ + private Response getSubscriberDetails(String subscriberId) { + File certiPath = GetCertificatesPath(); + Response resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId + "?depth=2", false); + //String resp = doAaiGet(certiPath.getAbsolutePath(), "business/customers/customer/" + subscriberId, false); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "getSubscriberDetails() resp=" + resp.getStatusInfo().toString()); + return resp; + } + + /** + * Gets the certificates path. + * + * @return the file + */ + private File GetCertificatesPath() { + if (servletContext != null) + return new File(servletContext.getRealPath("/WEB-INF/cert/")); + return null; + } + + /** + * Send a GET request to a&ai. + * + * @param certiPath the certi path + * @param uri the uri + * @param xml the xml + * @return String The response + */ + protected Response doAaiGet(String certiPath, String uri, boolean xml) { + String methodName = "getSubscriberList"; + String transId = UUID.randomUUID().toString(); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + Response resp = null; + try { + + AAIRestInterface restContrller = new AAIRestInterface(certiPath); + resp = restContrller.RestGet(fromAppId, transId, uri, xml); + + } catch (WebApplicationException e) { + final String message = ((BadRequestException) e).getResponse().readEntity(String.class); + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + message); + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + } + + return resp; + } + + /** + * Send a POST request to a&ai. + * + * @param certiPath the certi path + * @param uri the uri + * @param payload the payload + * @param xml the xml + * @return String The response + */ + protected Response doAaiPost(String certiPath, String uri, String payload, boolean xml) { + String methodName = "getSubscriberList"; + String transId = UUID.randomUUID().toString(); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + Response resp = null; + try { + + AAIRestInterface restContrller = new AAIRestInterface(certiPath); + resp = restContrller.RestPost(fromAppId, transId, uri, payload, xml); + + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + } + + return resp; + } + + /** + * Gets the component list put payload. + * + * @param namedQueryId the named query id + * @param globalCustomerId the global customer id + * @param serviceType the service type + * @param serviceInstance the service instance + * @return the component list put payload + */ + private String getComponentListPutPayload(String namedQueryId, String globalCustomerId, String serviceType, String serviceInstance) { + return + " {" + + " \"instance-filters\": {" + + " \"instance-filter\": [" + + " {" + + " \"customer\": {" + + " \"global-customer-id\": \"" + globalCustomerId + "\"" + + " }," + + " \"service-instance\": {" + + " \"service-instance-id\": \"" + serviceInstance + "\"" + + " }," + + " \"service-subscription\": {" + + " \"service-type\": \"" + serviceType + "\"" + + " }" + + " }" + + " ]" + + " }," + + " \"query-parameters\": {" + + " \"named-query\": {" + + " \"named-query-uuid\": \"" + namedQueryId + "\"" + + " }" + + " }" + + "}"; + + } + + private String getModelsByServiceTypePayload(String namedQueryId, String globalCustomerId, String serviceType) { + // TODO Auto-generated method stub + return " {" + + " \"instance-filters\": {" + + " \"instance-filter\": [" + + " {" + + " \"customer\": {" + + " \"global-customer-id\": \"" + globalCustomerId + "\"" + + " }," + + " \"service-subscription\": {" + + " \"service-type\": \"" + serviceType + "\"" + + " }" + + " }" + + " ]" + + " }," + + " \"query-parameters\": {" + + " \"named-query\": {" + + " \"named-query-uuid\": \"" + namedQueryId + "\"" + + " }" + + " }" + + "}"; + + } } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/ChangeManagementController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/ChangeManagementController.java new file mode 100644 index 000000000..1af715464 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/ChangeManagementController.java @@ -0,0 +1,71 @@ +package org.openecomp.vid.controller; + +import org.json.simple.JSONArray; +import org.openecomp.portalsdk.core.controller.UnRestrictedBaseController; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.services.ChangeManagementService; +import org.openecomp.vid.services.WorkflowService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import org.openecomp.vid.changeManagement.ChangeManagementRequest; +import org.openecomp.vid.mso.rest.Request; + +import java.io.IOException; +import java.util.Collection; + +import javax.servlet.http.HttpServletRequest; + +/** + * Controller to handle ChangeManagement feature requests. + */ +@RestController +@RequestMapping("change-management") +public class ChangeManagementController extends UnRestrictedBaseController { + private EELFLoggerDelegate logger; + private String fromAppId; + private final WorkflowService workflowService; + private final ChangeManagementService changeManagementService; + + @Autowired + public ChangeManagementController(WorkflowService workflowService, ChangeManagementService changeManagementService) { + this.logger = EELFLoggerDelegate.getLogger(ChangeManagementController.class); + this.fromAppId = "VidChangeManagementController"; + this.workflowService = workflowService; + this.changeManagementService = changeManagementService; + } + + @RequestMapping(value = {"/workflow"}, method = RequestMethod.GET) + public ResponseEntity> getWorkflow(@RequestParam("vnfs") Collection vnfs) throws IOException, InterruptedException { + Collection result = this.workflowService.getWorkflowsForVNFs(vnfs); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @RequestMapping(value = {"/mso"}, method = RequestMethod.GET) + public ResponseEntity> getMSOChangeManagements() throws IOException, InterruptedException { + Collection result = this.changeManagementService.getMSOChangeManagements(); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @RequestMapping(value = "/workflow/{vnfName}", method = RequestMethod.POST) + public ResponseEntity changeManagement(@PathVariable("vnfName") String vnfName, + HttpServletRequest request, + @RequestBody ChangeManagementRequest changeManagmentRequest) + throws Exception { + return this.changeManagementService.doChangeManagement(changeManagmentRequest, vnfName); + } + + + @RequestMapping(value = {"/scheduler"}, method = RequestMethod.GET) + public ResponseEntity getSchedulerChangeManagements() throws IOException, InterruptedException { + JSONArray result = this.changeManagementService.getSchedulerChangeManagements(); + return new ResponseEntity<>(result, HttpStatus.OK); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoConfig.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoConfig.java new file mode 100644 index 000000000..e0b59204a --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoConfig.java @@ -0,0 +1,29 @@ +package org.openecomp.vid.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.openecomp.vid.factories.MsoRequestFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class MsoConfig { + + /** + * Gets the object mapper. + * + * @return the object mapper + */ + @Bean + public ObjectMapper getObjectMapper() { + return new ObjectMapper(); + } + + @Bean + public MsoRequestFactory createRequestDetailsFactory(){ + return new MsoRequestFactory(); + } + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoController.java index 56fbd4cbd..9a064b000 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoController.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/MsoController.java @@ -21,35 +21,56 @@ package org.openecomp.vid.controller; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.glassfish.jersey.client.ClientResponse; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.openecomp.portalsdk.core.controller.RestrictedBaseController; -import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.openecomp.portalsdk.core.util.SystemProperties; -import org.openecomp.vid.model.ExceptionResponse; -import org.openecomp.vid.mso.*; -import org.openecomp.vid.mso.rest.RequestDetails; -import org.openecomp.vid.roles.RoleProvider; -import org.openecomp.vid.roles.RoleValidator; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +//import java.util.UUID; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Scanner; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.glassfish.jersey.client.ClientResponse; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.openecomp.vid.model.ExceptionResponse; +import org.openecomp.vid.mso.*; +import org.openecomp.vid.mso.rest.*; +import org.springframework.http.HttpStatus; +//import org.springframework.http.ResponseEntity; +//import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +import org.openecomp.portalsdk.core.controller.RestrictedBaseController; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.DeserializationFeature; /** * The Class MsoController. @@ -59,25 +80,30 @@ import java.util.Map; public class MsoController extends RestrictedBaseController { /** - * The Constant SVC_INSTANCE_ID. + * The view name. */ - public final static String SVC_INSTANCE_ID = ""; + String viewName; + /** - * The Constant VNF_INSTANCE_ID. + * The logger. */ - public final static String VNF_INSTANCE_ID = ""; + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoController.class); + /** * The Constant dateFormat. */ final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + /** - * The view name. + * The Constant SVC_INSTANCE_ID. */ - String viewName; + public final static String SVC_INSTANCE_ID = ""; + public final static String REQUEST_TYPE = ""; + /** - * The logger. + * The Constant VNF_INSTANCE_ID. */ - EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoController.class); + public final static String VNF_INSTANCE_ID = ""; /** * Welcome. @@ -118,37 +144,70 @@ public class MsoController extends RestrictedBaseController { */ @RequestMapping(value = "/mso_create_svc_instance", method = RequestMethod.POST) public ResponseEntity createSvcInstance(HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { + String methodName = "createSvcInstance"; + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + // always return OK, the MSO status code is embedded in the body + + MsoResponseWrapper w = mbl.createSvcInstance(mso_request); + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + + } + /** + * Creates the svc instance. + * + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + + public ResponseEntity createSvcInstanceNewRest(HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { String methodName = "createSvcInstance"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } -// mso_request = retrieveRequestObject (request, mso_request); + MsoBusinessLogicNew mbln = new MsoBusinessLogicNew(); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_SVC_INSTANCE); - String userId = ""; - HttpSession session = request.getSession(); - System.out.println((new ObjectMapper().writeValueAsString(session.getAttribute("roles")))); - MsoResponseWrapper w = createInstance(mso_request, p); - return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); // always return OK, the MSO status code is embedded in the body + MsoResponseWrapper w = mbln.createSvcInstanceRest(mso_request); + + if (w == null) { + return null; + } + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); } - private boolean userIsPermmited(HttpServletRequest request, RequestDetails mso_request) { + /** + * Creates the svc instance. + * + * @param request the request + * @return the response entity + * @throws Exception the exception + */ + + public ResponseEntity createSvcInstanceNew(HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { + String methodName = "createSvcInstance"; + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + MsoBusinessLogicNew mbln = new MsoBusinessLogicNew(); + // always return OK, the MSO status code is embedded in the body + + MsoResponseWrapper w = mbln.createSvcInstance(mso_request); - RoleValidator roleValidator = new RoleValidator(new RoleProvider().getUserRoles(request)); - boolean isPermitted = roleValidator.isMsoRequestValid(mso_request); - if (!isPermitted) { - return false; - } else { - return true; + if (w == null) { + return null; } + + return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); + } /** @@ -161,23 +220,10 @@ public class MsoController extends RestrictedBaseController { */ @RequestMapping(value = "/mso_create_vnf_instance/{serviceInstanceId}", method = RequestMethod.POST) public ResponseEntity createVnf(@PathVariable("serviceInstanceId") String serviceInstanceId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { -// if (!userIsPermmited(request, mso_request)) { - String instanceId = (String) ((Map)((Map)((ArrayList)((Map) mso_request.getAdditionalProperties().get("requestDetails")).get("relatedInstanceList")).get(0)).get("relatedInstance")).get("instanceId"); - ResponseEntity a = new AaiController(request.getServletContext()).doGetServiceInstance(instanceId,"Service Instance id"); -// return new ResponseEntity(HttpStatus.FORBIDDEN); -// } - String methodName = "createVnf"; - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - //RequestDetails mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VNF_INSTANCE); + MsoBusinessLogic mbl = new MsoBusinessLogic(); - if (p == null || p.isEmpty()) { - throw new Exception("Vnf instance path is not defined"); - } - // /serviceInstances/v2//vnfs - String vnf_path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - MsoResponseWrapper w = createInstance(mso_request, vnf_path); + MsoResponseWrapper w = mbl.createVnf(mso_request, serviceInstanceId); // always return OK, the MSO status code is embedded in the body @@ -195,23 +241,12 @@ public class MsoController extends RestrictedBaseController { */ @RequestMapping(value = "/mso_create_nw_instance/{serviceInstanceId}", method = RequestMethod.POST) public ResponseEntity createNwInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { - String methodName = "createNwInstance"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start, serviceInstanceId = " + serviceInstanceId); - //RequestDetails mso_request = retrieveRequestObject (request); - - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - - if (p == null || p.isEmpty()) { - throw new Exception("Network instance path is not defined"); - } - // /serviceInstances/v2//networks/ + MsoBusinessLogic mbl = new MsoBusinessLogic(); - String nw_path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - MsoResponseWrapper w = createInstance(mso_request, nw_path); - - // always return OK, the MSO status code is embedded in the body + MsoResponseWrapper w = mbl.createNwInstance(mso_request, serviceInstanceId); return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); @@ -230,21 +265,11 @@ public class MsoController extends RestrictedBaseController { public ResponseEntity createVolumeGroupInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { String methodName = "createVolumeGroupInstance"; - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - //RequestDetails mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + MsoBusinessLogic mbl = new MsoBusinessLogic(); - if (p == null || p.isEmpty()) { - throw new Exception("Volume group instance path is not defined"); - } - String path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - path = path.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - - MsoResponseWrapper w = createInstance(mso_request, path); + MsoResponseWrapper w = mbl.createVolumeGroupInstance(mso_request, serviceInstanceId, vnfInstanceId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); @@ -265,40 +290,31 @@ public class MsoController extends RestrictedBaseController { String methodName = "createVfModuleInstance"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } - //RequestDetails mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - if (p == null || p.isEmpty()) { - throw new Exception("VF module instance path is not defined"); - } - // /serviceInstances/v2//vnfs//vfmodules - String path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - path = path.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + MsoBusinessLogic mbl = new MsoBusinessLogic(); - MsoResponseWrapper w = createInstance(mso_request, path); + MsoResponseWrapper w = mbl.createVfModuleInstance(mso_request, serviceInstanceId, vnfInstanceId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); } - /** - * Creates the instance. - * - * @param request the request - * @param path the path - * @return the mso response wrapper - * @throws Exception the exception - */ - protected MsoResponseWrapper createInstance(RequestDetails request, String path) throws Exception { - String methodName = "createInstance"; - logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + /** + * Creates the instance. + * + * @param request the request + * @param path the path + * @return the mso response wrapper + * @throws ClientHandlerException the client handler exception + * @throws Exception the exception + */ + protected MsoResponseWrapper createInstance(RequestDetails request, String path) throws Exception { + String methodName = "createInstance"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); try { - MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); + MsoRestInterfaceIfc restController = new MsoRestInterface(); logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Post, request = (" + request + ")"); RestObject restObjStr = new RestObject(); @@ -307,14 +323,14 @@ public class MsoController extends RestrictedBaseController { restController.Post(str, request, "", path, restObjStr); MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); - return w; - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - throw e; - } - } + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + return w; + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } /** * Delete svc instance. @@ -331,10 +347,9 @@ public class MsoController extends RestrictedBaseController { String methodName = "deleteSvcInstance"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - //RequestDetails mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_SVC_INSTANCE); - String path = p + "/" + serviceInstanceId; - MsoResponseWrapper w = deleteInstance(mso_request, path); + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.deleteSvcInstance(mso_request, serviceInstanceId); logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); // always return OK, the MSO status code is embedded in the body @@ -359,17 +374,10 @@ public class MsoController extends RestrictedBaseController { String methodName = "deleteVnf"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } - //RequestDetails mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VNF_INSTANCE); - if (p == null || p.isEmpty()) { - throw new Exception("Vnf instance path is not defined"); - } - // /serviceInstances/v2//vnfs/ - String vnf_path = p.replaceFirst(SVC_INSTANCE_ID, vnfInstanceId); - MsoResponseWrapper w = deleteInstance(mso_request, vnf_path + "/" + vnfInstanceId); + + MsoBusinessLogic mlb = new MsoBusinessLogic(); + + MsoResponseWrapper w = mlb.deleteVnf(mso_request, serviceInstanceId, vnfInstanceId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); @@ -393,21 +401,11 @@ public class MsoController extends RestrictedBaseController { @PathVariable("vfModuleId") String vfModuleId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { String methodName = "deleteVfModule"; - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } - //RequestDetails mso_request = new RequestDetails(); - //mso_request = retrieveRequestObject (request); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - if (p == null || p.isEmpty()) { - throw new Exception("VF Module instance path is not defined"); - } - // /serviceInstances/v2//vnfs//vfmodules - String path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - path = path.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - MsoResponseWrapper w = deleteInstance(mso_request, path + "/" + vfModuleId); + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.deleteVfModule(mso_request, serviceInstanceId, vnfInstanceId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); @@ -428,21 +426,12 @@ public class MsoController extends RestrictedBaseController { public ResponseEntity deleteVolumeGroupInstance( @PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("vnfInstanceId") String vnfInstanceId, @PathVariable("volumeGroupId") String volumeGroupId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { - String methodName = "deleteVolumeGroupInstance"; - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); - if (p == null || p.isEmpty()) { - throw new Exception("Volume group instance path is not defined"); - } - // /serviceInstances/v2/{serviceInstanceId}/volumeGroups - String path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - path = path.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - MsoResponseWrapper w = deleteInstance(mso_request, path + "/" + volumeGroupId); + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.deleteVolumeGroupInstance(mso_request, serviceInstanceId, vnfInstanceId, volumeGroupId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); @@ -460,60 +449,18 @@ public class MsoController extends RestrictedBaseController { @RequestMapping(value = "/mso_delete_nw_instance/{serviceInstanceId}/networks/{networkInstanceId}", method = RequestMethod.POST) public ResponseEntity deleteNwInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @PathVariable("networkInstanceId") String networkInstanceId, HttpServletRequest request, @RequestBody RequestDetails mso_request) throws Exception { - String methodName = "deleteNwInstance"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - //RequestDetails mso_request = retrieveRequestObject (request); - if (!userIsPermmited(request, mso_request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - if (p == null || p.isEmpty()) { - throw new Exception("Network instance path is not defined"); - } - // /serviceInstances/v2//networks - String path = p.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - MsoResponseWrapper w = deleteInstance(mso_request, path + "/" + networkInstanceId); + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.deleteNwInstance(mso_request, serviceInstanceId, networkInstanceId); // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); } - /** - * Delete instance. - * - * @param request the request - * @param path the path - * @return the mso response wrapper - * @throws Exception the exception - */ - protected MsoResponseWrapper deleteInstance(RequestDetails request, String path) throws Exception { - String methodName = "deleteInstance"; - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - - try { - MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Delete, path =[" + path + "]"); - - RestObject restObjStr = new RestObject(); - String str = new String(); - restObjStr.set(str); - restController.Delete(str, request, "", path, restObjStr); - MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); - - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); - return w; - - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - throw e; - } - - } - /** * Gets the orchestration request. * @@ -528,27 +475,12 @@ public class MsoController extends RestrictedBaseController { String methodName = "getOrchestrationRequest"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - MsoResponseWrapper w = null; - try { - MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQ); - String path = p + "/" + requestId; - RestObject restObjStr = new RestObject(); - String str = new String(); - restObjStr.set(str); - restController.Get(str, "", path, restObjStr); + MsoBusinessLogic mbl = new MsoBusinessLogic(); - w = MsoUtil.wrapResponse(restObjStr); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); - // always return OK, the MSO status code is embedded in the body + MsoResponseWrapper w = mbl.getOrchestrationRequest(requestId); - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - throw e; - } // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); } @@ -568,63 +500,134 @@ public class MsoController extends RestrictedBaseController { String methodName = "getOrchestrationRequests"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - MsoResponseWrapper w = null; - try { - MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQS); - String path = p + filterString; - RestObject restObjStr = new RestObject(); - String str = new String(); - restObjStr.set(str); - restController.Get(str, "", path, restObjStr); + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.getOrchestrationRequests(filterString); - w = MsoUtil.wrapResponse(restObjStr); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - throw e; - } // always return OK, the MSO status code is embedded in the body return (new ResponseEntity(w.getResponse(), HttpStatus.OK)); } + /** - * Gets the orchestration requests for svc instance. + * activate to a pnf instance. * - * @param svc_instance_id the svc instance id - * @return the orchestration requests for svc instance + * @param serviceInstanceId the id of the service. + * @param requestDetails the body of the request. + * @return the response entity * @throws Exception the exception */ - public MsoResponseWrapper getOrchestrationRequestsForSvcInstance(String svc_instance_id) throws Exception { + @RequestMapping(value = "/mso_activate_service_instance/{serviceInstanceId}", method = RequestMethod.POST) + public ResponseEntity activateServiceInstance(@PathVariable("serviceInstanceId") String serviceInstanceId, @RequestBody RequestDetails requestDetails) throws Exception { + String methodName = "activateServiceInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.activateServiceInstance(requestDetails, serviceInstanceId); + return new ResponseEntity<>(w.getResponse(), HttpStatus.OK); + } + - String methodName = "getOrchestrationRequestsForSvcInstance"; + /** + * Gets the orchestration requests for the dashboard. + * currently its all the orchestration requests with RequestType updateInstance or replaceInstance. + * @return the orchestration requests + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_orch_reqs/dashboard", method = RequestMethod.GET) + public List getOrchestrationRequestsForDashboard() throws Exception { + + String methodName = "getOrchestrationRequestsForDashboard"; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); - MsoResponseWrapper w = null; - try { - MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); - String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQS); - String path = p + svc_instance_id; - RestObject restObjStr = new RestObject(); - String str = new String(); - restObjStr.set(str); + MsoBusinessLogic mbl = new MsoBusinessLogic(); - restController.Get(str, "", path, restObjStr); - w = MsoUtil.wrapResponse(restObjStr); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + return mbl.getOrchestrationRequestsForDashboard(); + } - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); - throw e; - } - return w; + /** + * Gets the Manual Tasks for the given request id. + * + * @param originalRequestId the id of the original request. + * @return the tasks + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_get_man_task/{originalRequestId}", method = RequestMethod.GET) + public List getManualTasksByRequestId(@PathVariable("originalRequestId") String originalRequestId) throws Exception { + + String methodName = "getManualTasksByRequestId"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + return mbl.getManualTasksByRequestId(originalRequestId); + } + + + + /** + * Complete the manual task. + * + * @param taskId the id of the task to complete. + * @param requestDetails the body of the request. + * @return the response entity + * @throws Exception the exception + */ + @RequestMapping(value = "/mso_post_man_task/{taskId}", method = RequestMethod.POST) + public ResponseEntity manualTaskComplete(@PathVariable("taskId") String taskId , @RequestBody RequestDetails requestDetails) throws Exception { + + String methodName = "manualTaskComplete"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + MsoBusinessLogic mbl = new MsoBusinessLogic(); + + MsoResponseWrapper w = mbl.completeManualTask(requestDetails, taskId); + return new ResponseEntity(w.getResponse(), HttpStatus.OK); } + + + + + /** + * Gets the orchestration requests for svc instance. + * + * @param svc_instance_id the svc instance id + * @return the orchestration requests for svc instance + * @throws Exception the exception + */ +// public MsoResponseWrapper getOrchestrationRequestsForSvcInstance(String svc_instance_id) throws Exception { + +// String methodName = "getOrchestrationRequestsForSvcInstance"; +// logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); +// MsoResponseWrapper w = null; +// +// try { +// MsoRestInterfaceIfc restController = MsoRestInterfaceFactory.getInstance(); +// String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQS); +// String path = p + svc_instance_id; +// +// RestObject restObjStr = new RestObject(); +// String str = new String(); +// restObjStr.set(str); +// +// restController.Get(str, "", path, restObjStr); +// w = MsoUtil.wrapResponse(restObjStr); +// logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); +// +// } catch (Exception e) { +// logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); +// logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); +// throw e; +// } +// return w; +// } + /** * Exception handler. * @@ -636,7 +639,7 @@ public class MsoController extends RestrictedBaseController { private void exceptionHandler(Exception e, HttpServletResponse response) throws IOException { /* - * The following "logger.error" lines "should" be sufficient for logging the exception. + * The following "logger.error" lines "should" be sufficient for logging the exception. * However, the console output in my Eclipse environment is NOT showing ANY of the * logger statements in this class. Thus the temporary "e.printStackTrace" statement * is also included. @@ -649,7 +652,7 @@ public class MsoController extends RestrictedBaseController { logger.error(EELFLoggerDelegate.errorLogger, sw.toString()); /* - * Temporary - IF the above mentioned "logger.error" glitch is resolved ... + * Temporary - IF the above mentioned "logger.error" glitch is resolved ... * this statement could be removed since it would then likely result in duplicate * trace output. */ @@ -673,7 +676,8 @@ public class MsoController extends RestrictedBaseController { * * @param resp the resp * @return the list - * @throws Exception the exception + * @throws ParseException the parse exception + * @throws Exception the exception */ @SuppressWarnings("unchecked") public List parseOrchestrationRequestsForSvcInstance(ClientResponse resp) throws org.json.simple.parser.ParseException, Exception { diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/PolicyController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/PolicyController.java new file mode 100644 index 000000000..83e177a61 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/PolicyController.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.controller; + +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; + +import org.json.simple.JSONObject; +import org.openecomp.portalsdk.core.controller.RestrictedBaseController; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.policy.PolicyProperties; +import org.openecomp.vid.policy.PolicyResponseWrapper; +import org.openecomp.vid.policy.PolicyRestInterfaceFactory; +import org.openecomp.vid.policy.PolicyRestInterfaceIfc; +import org.openecomp.vid.policy.PolicyUtil; +import org.openecomp.vid.policy.RestObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * Controller to handle Policy requests. + */ + +@RestController +public class PolicyController extends RestrictedBaseController{ + + /** The logger. */ + static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PolicyController.class); + + @RequestMapping(value="/get_policy",method = RequestMethod.POST) + public ResponseEntity getPolicyInfo( HttpServletRequest request, @RequestBody JSONObject policy_request) throws Exception { + + logger.debug("#####################POLICY API CALL STARTED ###############"+ PolicyProperties.POLICY_GET_CONFIG_VAL); + logger.debug("#####################Policy Request ###############"+policy_request.toString()); + + String path = PolicyProperties.getProperty(PolicyProperties.POLICY_GET_CONFIG_VAL); + PolicyResponseWrapper policyResWrapper = getPolicyConfig(policy_request,path); + + logger.debug("$$$$$$$$$$$$$$$$$$$$$$ " + new ResponseEntity(policyResWrapper.getResponse(), HttpStatus.OK).toString()); + + return ( new ResponseEntity(policyResWrapper.getResponse(), HttpStatus.valueOf(policyResWrapper.getStatus())) ); + } + + protected static PolicyResponseWrapper getPolicyConfig(JSONObject request, String path) throws Exception { + String methodName = "getPolicyConfig"; + String uuid = UUID.randomUUID().toString(); + logger.debug( "starting getPolicyConfig "); + + try { + //STARTING REST API CALL AS AN FACTORY INSTACE + PolicyRestInterfaceIfc restController = PolicyRestInterfaceFactory.getInstance(); + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + restController.Post(str, request, uuid, path, restObjStr ); + PolicyResponseWrapper policyRespWrapper = PolicyUtil.wrapResponse (restObjStr); + + logger.debug( "<== " + methodName + " w=" + policyRespWrapper.getResponse()); + return policyRespWrapper; + } catch (Exception e) { + logger.debug( "EXCEPTION in getPolicyConfig <== " + "." + methodName + e.toString()); + throw e; + } + } +} + diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/SchedulerController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/SchedulerController.java new file mode 100644 index 000000000..0fd2079e9 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/SchedulerController.java @@ -0,0 +1,244 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.controller; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; + +import org.json.simple.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import org.openecomp.portalsdk.core.controller.RestrictedBaseController; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.scheduler.RestObjects.GetTimeSlotsRestObject; +import org.openecomp.vid.scheduler.RestObjects.PostCreateNewVnfRestObject; +import org.openecomp.vid.scheduler.RestObjects.PostSubmitVnfChangeRestObject; +import org.openecomp.vid.scheduler.SchedulerProperties; +import org.openecomp.vid.scheduler.SchedulerRestInterface; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.GetTimeSlotsWrapper; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.PostCreateNewVnfWrapper; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.PostSubmitVnfChangeTimeSlotsWrapper; +import org.openecomp.vid.scheduler.SchedulerUtil; + +/** + * Controller to handle Scheduler requests. + */ + +@RestController +public class SchedulerController extends RestrictedBaseController { + + static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerController.class); + + /** The request date format. */ + public DateFormat requestDateFormat = new SimpleDateFormat("EEE, dd MMM YYYY HH:mm:ss z"); + + @Autowired + private SchedulerRestInterface restController; + + /* + * + * GET SCHEDULER CONTROLLERS + * + */ + + @RequestMapping(value = "/get_time_slots/{scheduler_request}", method = RequestMethod.GET) + public ResponseEntity getTimeSlots(HttpServletRequest request, @PathVariable("scheduler_request") String scheduler_request) throws Exception { + + Date startingTime = new Date(); + String startTimeRequest = requestDateFormat.format(startingTime); + + System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + System.out.println(startTimeRequest + " | Controller Scheduler GET : /get_time_slots/{scheduler_request} \n"); + System.out.println("Original Request : \n " + scheduler_request + '\n'); + + String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_GET_TIME_SLOTS) + scheduler_request; + + GetTimeSlotsWrapper schedulerResWrapper = getTimeSlots(scheduler_request, path, scheduler_request); + + Date endTime = new Date(); + String endTimeRequest = requestDateFormat.format(endTime); + System.out.println(endTimeRequest + " | Controller Scheduler - GET\n"); + + return (new ResponseEntity(schedulerResWrapper.getResponse(), HttpStatus.OK)); + + } + + protected GetTimeSlotsWrapper getTimeSlots(String request, String path, String uuid) throws Exception { + + try { + //STARTING REST API CALL AS AN FACTORY INSTACE + System.out.println("<== Get Time Slots Request START \n"); + + GetTimeSlotsRestObject restObjStr = new GetTimeSlotsRestObject(); + String str = new String(); + + restObjStr.set(str); + + restController.Get(str, uuid, path, restObjStr); + GetTimeSlotsWrapper schedulerRespWrapper = SchedulerUtil.getTimeSlotsWrapResponse(restObjStr); + + System.out.println("<== Get Time Slots Request END : Response = " + schedulerRespWrapper.getResponse() + '\n'); + + return schedulerRespWrapper; + + } catch (Exception e) { + System.out.println("<== Get Time Slots Request ERROR : " + e.toString() + '\n'); + throw e; + } + } + + /* + * + * POST SCHEDULER CONTROLLERS + * + */ + + @SuppressWarnings("unchecked") + @RequestMapping(value = "/post_create_new_vnf_change", method = RequestMethod.POST) + public ResponseEntity postCreateNewVNFChange(HttpServletRequest request, @RequestBody JSONObject scheduler_request) throws Exception { + + Date startingTime = new Date(); + String startTimeRequest = requestDateFormat.format(startingTime); + + System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + System.out.println(startTimeRequest + " | Controller Scheduler POST : post_create_new_vnf_change \n"); + + //Generating uuid + String uuid = UUID.randomUUID().toString(); + + scheduler_request.put("scheduleId", uuid); + System.out.println("<== UUID : " + uuid + '\n'); + + //adding uuid to the request payload + scheduler_request.put("scheduleId", uuid); + + System.out.println("<== UUID : " + uuid + '\n'); + System.out.println("Original Request : \n " + scheduler_request.toString() + '\n'); + + String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_CREATE_NEW_VNF_CHANGE_INSTANCE_VAL) + uuid; + + PostCreateNewVnfWrapper responseWrapper = postSchedulingRequest(scheduler_request, path, uuid); + + Date endTime = new Date(); + String endTimeRequest = requestDateFormat.format(endTime); + System.out.println(endTimeRequest + " | Controller Scheduler - POST\n"); + + return (new ResponseEntity(responseWrapper.getResponse(), HttpStatus.OK)); + } + + protected PostCreateNewVnfWrapper postSchedulingRequest(JSONObject request, String path, String uuid) throws Exception { + + try { + //STARTING REST API CALL AS AN FACTORY INSTACE + System.out.println("<== Post Create New Vnf Scheduling Request START \n"); + + PostCreateNewVnfRestObject restObjStr = new PostCreateNewVnfRestObject(); + String str = new String(); + + restObjStr.set(str); + restController.Post(str, request, path, restObjStr); + + int status = restObjStr.getStatusCode(); + if (status >= 200 && status <= 299) { + restObjStr.setUUID(uuid); + } + + PostCreateNewVnfWrapper responseWrapper = SchedulerUtil.postCreateNewVnfWrapResponse(restObjStr); + + System.out.println("<== Post Create New Vnf Scheduling Request END : Response = " + responseWrapper.getResponse() + '\n'); + + return responseWrapper; + + } catch (Exception e) { + System.out.println("<== Post Create New Vnf Scheduling Request ERROR : " + e.toString() + '\n'); + throw e; + } + } + + @RequestMapping(value = "/submit_vnf_change_timeslots", method = RequestMethod.POST) + public ResponseEntity postSubmitVnfChangeTimeslots(HttpServletRequest request, @RequestBody JSONObject scheduler_request) throws Exception { + + Date startingTime = new Date(); + String startTimeRequest = requestDateFormat.format(startingTime); + + System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + System.out.println(startTimeRequest + " | Controller Scheduler POST : submit_vnf_change_timeslots \n"); + + //Generating uuid + String uuid = (String) scheduler_request.get("scheduleId"); + scheduler_request.remove("scheduleId"); + + System.out.println("<== UUID : " + uuid + '\n'); + System.out.println("Original Request : \n " + scheduler_request.toString() + '\n'); + + String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SUBMIT_NEW_VNF_CHANGE).replace("{scheduleId}", uuid); + + PostSubmitVnfChangeTimeSlotsWrapper responseWrapper = postSubmitSchedulingRequest(scheduler_request, path, uuid); + + Date endTime = new Date(); + String endTimeRequest = requestDateFormat.format(endTime); + System.out.println(endTimeRequest + " | Controller Scheduler - POST Submit\n"); + + return (new ResponseEntity(responseWrapper.getResponse(), HttpStatus.OK)); + } + + protected PostSubmitVnfChangeTimeSlotsWrapper postSubmitSchedulingRequest(JSONObject request, String path, String uuid) throws Exception { + + try { + //STARTING REST API CALL AS AN FACTORY INSTACE + System.out.println("<== Post Submit Scheduling Request START \n"); + + PostSubmitVnfChangeRestObject restObjStr = new PostSubmitVnfChangeRestObject(); + String str = new String(); + + restObjStr.set(str); + restController.Post(str, request, path, restObjStr); + + int status = restObjStr.getStatusCode(); + if (status >= 200 && status <= 299) { + restObjStr.setUUID(uuid); + } + + PostSubmitVnfChangeTimeSlotsWrapper responseWrapper = SchedulerUtil.postSubmitNewVnfWrapResponse(restObjStr); + + System.out.println("<== Post Submit Scheduling Request END : Response = " + responseWrapper.getResponse() + '\n'); + + return responseWrapper; + + } catch (Exception e) { + System.out.println("<== Post Submit Scheduling Request ERROR : " + e.toString() + '\n'); + throw e; + } + } +} + diff --git a/vid-app-common/src/main/java/org/openecomp/vid/controller/VidController.java b/vid-app-common/src/main/java/org/openecomp/vid/controller/VidController.java index 838793a76..aac3a0b7e 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/controller/VidController.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/controller/VidController.java @@ -67,6 +67,7 @@ public class VidController extends RestrictedBaseController { @RequestMapping(value={"/rest/models/services"}, method = RequestMethod.GET) public SecureServices getServices(HttpServletRequest request) throws VidServiceUnavailableException { try { + LOG.info("Start API for browse ASDC was called"); SecureServices secureServices = new SecureServices(); RoleProvider roleProvider = new RoleProvider(); Map requestParams = request.getParameterMap(); diff --git a/vid-app-common/src/main/java/org/openecomp/vid/factories/MsoRequestFactory.java b/vid-app-common/src/main/java/org/openecomp/vid/factories/MsoRequestFactory.java new file mode 100644 index 000000000..9cc9c5f66 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/factories/MsoRequestFactory.java @@ -0,0 +1,15 @@ +package org.openecomp.vid.factories; + +import org.openecomp.vid.mso.rest.RequestDetails; + +/** + * Created by pickjonathan on 19/06/2017. + */ +public class MsoRequestFactory { + + public RequestDetails createMsoRequest(String path) + { + return null; + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/model/CommandProperty.java b/vid-app-common/src/main/java/org/openecomp/vid/model/CommandProperty.java index fe114c380..740f9d781 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/model/CommandProperty.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/model/CommandProperty.java @@ -1,9 +1,9 @@ /*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,7 +14,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ============LICENSE_END========================================================= */ diff --git a/vid-app-common/src/main/java/org/openecomp/vid/model/VersionByInvariantIdsRequest.java b/vid-app-common/src/main/java/org/openecomp/vid/model/VersionByInvariantIdsRequest.java new file mode 100644 index 000000000..7c86165b4 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/model/VersionByInvariantIdsRequest.java @@ -0,0 +1,11 @@ +package org.openecomp.vid.model; + +import java.util.List; + +/** + * Created by Oren on 9/5/17. + */ +public class VersionByInvariantIdsRequest { + + public List versions; +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/model/VolumeGroup.java b/vid-app-common/src/main/java/org/openecomp/vid/model/VolumeGroup.java index d09ef9a33..baa535171 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/model/VolumeGroup.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/model/VolumeGroup.java @@ -161,7 +161,7 @@ public class VolumeGroup { * * @param u the new customization uuid */ - private void setCustomizationUuid(String u) { + public void setCustomizationUuid(String u) { this.customizationUuid = u; } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/model/Workflow.java b/vid-app-common/src/main/java/org/openecomp/vid/model/Workflow.java new file mode 100644 index 000000000..6032ec5aa --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/model/Workflow.java @@ -0,0 +1,47 @@ +package org.openecomp.vid.model; + + +import java.util.Collection; + +public class Workflow { + //Private members: + private int id; + private String workflowName; + private Collection vnfNames; + + + //Constructors: + public Workflow() {} + + public Workflow(int id, String workflowName, Collection vnfNames) { + this.id = id; + this.workflowName = workflowName; + this.vnfNames = vnfNames; + } + + + //Setters and getters: + public int getId() { + return id; + } + + public String getWorkflowName() { + return workflowName; + } + + public Collection getVnfNames() { + return this.vnfNames; + } + + public void setId(int id) { + this.id = id; + } + + public void setWorkflowName(String workflowName) { + this.workflowName = workflowName; + } + + public void setVnfName(Collection vnfNames) { + this.vnfNames = vnfNames; + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoBusinessLogic.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoBusinessLogic.java new file mode 100644 index 000000000..cd6003ad4 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoBusinessLogic.java @@ -0,0 +1,415 @@ +package org.openecomp.vid.mso; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.controller.MsoController; +import org.openecomp.vid.mso.rest.*; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import static org.openecomp.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.openecomp.vid.controller.MsoController.REQUEST_TYPE; +import static org.openecomp.vid.controller.MsoController.VNF_INSTANCE_ID; + +/** + * Created by pickjonathan on 19/06/2017. + */ +public class MsoBusinessLogic { + + /** + * The Mso REST client + * This should be replaced with mso client factory. + */ + private MsoInterface msoClientInterface; + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoController.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + public MsoBusinessLogic() { + msoClientInterface = MsoRestInterfaceFactory.getInstance(); + } + + // this function should get params from tosca and send them to instance at mso, then return success response. + public MsoResponseWrapper createSvcInstance(RequestDetails msoRequest) throws Exception { + String methodName = "createSvcInstance "; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_SVC_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + return msoClientInterface.createSvcInstance(msoRequest, endpoint); + } + + public MsoResponseWrapper createVnf(RequestDetails requestDetails, String serviceInstanceId) throws Exception { + String methodName = "createVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String vnf_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + return msoClientInterface.createVnf(requestDetails, vnf_endpoint); + } + + public MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String serviceInstanceId) throws Exception { + String methodName = "createNwInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String nw_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + return msoClientInterface.createNwInstance(requestDetails, nw_endpoint); + } + + public MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception { + String methodName = "createVolumeGroupInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String vnf_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + vnf_endpoint = vnf_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + + return msoClientInterface.createVolumeGroupInstance(requestDetails, vnf_endpoint); + } + + public MsoResponseWrapper createVfModuleInstance(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception{ + String methodName = "createVfModuleInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String partial_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vf_module_endpoint = partial_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + + return msoClientInterface.createVfModuleInstance(requestDetails, vf_module_endpoint); + } + + public MsoResponseWrapper deleteSvcInstance(RequestDetails requestDetails, String serviceInstanceId) throws Exception{ + String methodName = "deleteSvcInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_SVC_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String svc_endpoint = endpoint + "/" + serviceInstanceId; + + return msoClientInterface.deleteSvcInstance(requestDetails, svc_endpoint); + } + + public MsoResponseWrapper deleteVnf(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception{ + String methodName = "deleteVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE); + } catch (Exception exception) { + throw exception; + } + String vnf_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + vnf_endpoint = vnf_endpoint + '/' + vnfInstanceId; + + return msoClientInterface.deleteVnf(requestDetails, vnf_endpoint); + } + + public MsoResponseWrapper deleteVfModule(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception{ + String methodName = "deleteVfModule"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String delete_vf_endpoint = svc_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + + return msoClientInterface.deleteVfModule(requestDetails, delete_vf_endpoint); + } + + public MsoResponseWrapper deleteVolumeGroupInstance(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId, String volumeGroupId)throws Exception{ + String methodName = "deleteVolumeGroupInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vnf_endpoint = svc_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String delete_volume_group_endpoint = vnf_endpoint + "/" + volumeGroupId; + + return msoClientInterface.deleteVolumeGroupInstance(requestDetails, delete_volume_group_endpoint); + } + + public MsoResponseWrapper deleteNwInstance(RequestDetails requestDetails, String serviceInstanceId, String networkInstanceId) throws Exception{ + String methodName = "deleteNwInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + } catch (Exception exception) { + throw exception; + } + + String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String delete_nw_endpoint = svc_endpoint + "/" + networkInstanceId; + + return msoClientInterface.deleteNwInstance(requestDetails, delete_nw_endpoint); + } + + public MsoResponseWrapper getOrchestrationRequest(String requestId)throws Exception{ + String methodName = "getOrchestrationRequest"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + MsoResponseWrapper w = null; + try { + String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQ); + String path = p + "/" + requestId; + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + + msoClientInterface.getOrchestrationRequest(str, "", path, restObjStr); + + return MsoUtil.wrapResponse(restObjStr); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + public MsoResponseWrapper getOrchestrationRequests(String filterString)throws Exception{ + String methodName = "getOrchestrationRequest"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + MsoResponseWrapper w = null; + try { + String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQS); + String path = p + filterString; + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + + msoClientInterface.getOrchestrationRequest(str, "", path, restObjStr); + + return MsoUtil.wrapResponse(restObjStr); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + public List getOrchestrationRequestsForDashboard()throws Exception{ + String methodName = "getOrchestrationRequestsForDashboard"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + String path = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_ORC_REQS); + path += "filter=modelType:EQUALS:vnf"; + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + + MsoResponseWrapper msoResponseWrapper = msoClientInterface.getOrchestrationRequestsForDashboard(str, "", path, restObjStr); + List allOrchestrationRequests = deserializeOrchestrationRequestsJson(msoResponseWrapper.getEntity()); + + List filteredOrchestrationRequests = new ArrayList<>(); + for (RequestWrapper currentRequest:allOrchestrationRequests){ + if ((currentRequest.getRequest() != null) && (currentRequest.getRequest().getRequestScope() == Request.RequestScope.VNF) && ((currentRequest.getRequest().getRequestType() == + Request.RequestType.REPLACE_INSTANCE)||(currentRequest.getRequest().getRequestType() == + Request.RequestType.UPDATE_INSTANCE) )) { + filteredOrchestrationRequests.add(currentRequest.getRequest()); + } + } + return filteredOrchestrationRequests; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + + } + + private List deserializeOrchestrationRequestsJson(String orchestrationRequestsJson) throws Exception { + String methodName = "deserializeOrchestrationRequestsJson"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); + RequestList requestList = mapper.readValue(orchestrationRequestsJson , RequestList.class); + return requestList.getRequestList(); + } + + + public List getManualTasksByRequestId(String originalRequestId)throws Exception{ + String methodName = "getManualTasksByRequestId"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_MAN_TASKS); + String path = p + "?originalRequestId=" + originalRequestId; + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + + MsoResponseWrapper msoResponseWrapper = msoClientInterface.getManualTasksByRequestId(str, "", path, restObjStr); + return deserializeManualTasksJson(msoResponseWrapper.getEntity()); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + private List deserializeManualTasksJson(String manualTasksJson) throws Exception{ + String methodName = "deserializeManualTasksJson"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + ObjectMapper mapper = new ObjectMapper(); + TaskList taskList = mapper.readValue(manualTasksJson , TaskList.class); + return taskList.getTaskList(); + } + + + public MsoResponseWrapper completeManualTask(RequestDetails requestDetails , String taskId)throws Exception{ + String methodName = "completeManualTask"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + MsoResponseWrapper w = null; + try { + String p = SystemProperties.getProperty(MsoProperties.MSO_REST_API_GET_MAN_TASKS); + String path = p + "/" + taskId + "/complete"; + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + + msoClientInterface.completeManualTask(requestDetails , str, "", path, restObjStr); + + return MsoUtil.wrapResponse(restObjStr); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + public MsoResponseWrapper activateServiceInstance(RequestDetails requestDetails , String serviceInstanceId)throws Exception{ + String methodName = "activateServiceInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + try { + String path ="/" + serviceInstanceId + "/activate"; + + RestObject restObjStr = new RestObject<>(); + String str = ""; + restObjStr.set(str); + + msoClientInterface.activateServiceInstance(requestDetails , str, "", path, restObjStr); + + return MsoUtil.wrapResponse(restObjStr); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + + + + private String validateEndpointPath(String endpointEnvVariable) throws Exception { + String endpoint = SystemProperties.getProperty(endpointEnvVariable); + if (endpoint == null || endpoint.isEmpty()) { + throw new Exception(endpointEnvVariable + " env variable is not defined"); + } + return endpoint; + } + + public MsoResponseWrapper updateVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception { + String methodName = "updateVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE); + } catch (Exception exception) { + throw exception; + } + String vnf_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + vnf_endpoint = vnf_endpoint + '/' + vnfInstanceId; + return msoClientInterface.updateVnf(requestDetails, vnf_endpoint); + } + + public MsoResponseWrapper replaceVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) throws Exception { + String methodName = "replaceVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + String endpoint; + try { + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VNF_CHANGE_MANAGEMENT_INSTANCE); + } catch (Exception exception) { + throw exception; + } + String vnf_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + vnf_endpoint = vnf_endpoint.replace(VNF_INSTANCE_ID, vnfInstanceId); + vnf_endpoint = vnf_endpoint.replace(REQUEST_TYPE, "replace"); //No Constants file, TODO: once you create - add it. + return msoClientInterface.replaceVnf(requestDetails, vnf_endpoint); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoClientFactory.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoClientFactory.java new file mode 100644 index 000000000..fb0ead440 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoClientFactory.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.mso; + +import org.openecomp.vid.mso.rest.MsoRestClientNew; + +/** + * A factory for creating MsoRestInterface objects. + */ +public class MsoClientFactory { + + /** + * MSO client factory that creates the right client according to env. + * @return + */ + public static MsoInterface getInstance() { + return new MsoRestClientNew(); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoInterface.java new file mode 100644 index 000000000..cdeb1bbd2 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoInterface.java @@ -0,0 +1,75 @@ +package org.openecomp.vid.mso; + +import org.openecomp.vid.mso.rest.Request; +import org.openecomp.vid.mso.rest.RequestDetails; +import org.openecomp.vid.mso.rest.Task; + +import java.util.List; + +/** + * Created by pickjonathan on 21/06/2017. + */ +public interface MsoInterface { + + /** + * This function will post MSO service with information about how to instantiate the requested service + * @param requestDetails The details about the service as they come from the web. + * @return MsoResponseWrapper containing information about the service instantiation + * --> success : see JSON at resources folder mso_create_instance_response. + * --> failure : would return 200 with failure data. + * @throws Exception + */ + MsoResponseWrapper createSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception; + + /** + * will create a virtual network function using MSO service. + * @param requestDetails - information about the vnf to create + * @return - the response body recived from MSO + * @throws Exception + */ + MsoResponseWrapper createVnf(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String endpoint) throws Exception; + /** + * + * @param requestDetails + * @param path + * @return + * @throws Exception + */ + MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String path) throws Exception; + + /** + * + * @param requestDetails + * @return + * @throws Exception + */ + MsoResponseWrapper createVfModuleInstance(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper deleteSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper deleteVnf(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper deleteVfModule(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper deleteVolumeGroupInstance(RequestDetails requestDetails, String endpoint) throws Exception; + + MsoResponseWrapper deleteNwInstance(RequestDetails requestDetails, String endpoint) throws Exception; + + void getOrchestrationRequest(String t, String sourceId, String endpoint, RestObject restObject) throws Exception; + + MsoResponseWrapper getOrchestrationRequestsForDashboard(String t , String sourceId , String endpoint , RestObject restObject) throws Exception; + + MsoResponseWrapper getManualTasksByRequestId(String t , String sourceId , String endpoint , RestObject restObject) throws Exception; + + MsoResponseWrapper completeManualTask(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception; + + MsoResponseWrapper updateVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String vnf_endpoint) throws Exception; + + MsoResponseWrapper replaceVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String vnf_endpoint) throws Exception; + + + void activateServiceInstance(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClient.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClient.java new file mode 100644 index 000000000..0179400dc --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClient.java @@ -0,0 +1,85 @@ +package org.openecomp.vid.mso; + +import org.apache.commons.io.IOUtils; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.changeManagement.ChangeManagementRequest; +import org.openecomp.vid.controller.VidController; +import org.openecomp.vid.mso.rest.RequestDetails; + +import javax.ws.rs.client.Client; +import javax.ws.rs.core.MultivaluedHashMap; +import java.io.InputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +/** + * Created by pickjonathan on 20/06/2017. + */ +public class MsoLocalClient implements MsoRestInterfaceIfc { + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoLocalClient.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** + * The client. + */ + private static Client client = null; + + /** + * The common headers. + */ + private MultivaluedHashMap commonHeaders; + + /** + * Instantiates a new mso rest interface. + */ + public MsoLocalClient() { + super(); + } + + public void initMsoClient() { + final String methodname = "initRestClient()"; + } + + @Override + public void Get(T t, String sourceId, String path, RestObject restObject) throws Exception { + + } + + @Override + public void Delete(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception { + + } + + @Override + public void Post(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception { + initMsoClient(); + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_create_instance_response.json"); + + t = (T) IOUtils.toString(asdcServicesFile); + restObject.setStatusCode(200); + restObject.set(t); + } + + @Override + public void logRequest(RequestDetails r) { + + } + + @Override + public void Put(T t, ChangeManagementRequest r, String sourceID, String path, RestObject restObject) + throws Exception { + + + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClientNew.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClientNew.java new file mode 100644 index 000000000..1b15df721 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoLocalClientNew.java @@ -0,0 +1,216 @@ +package org.openecomp.vid.mso; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.NotImplementedException; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.mso.rest.*; + +import java.io.InputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by pickjonathan on 21/06/2017. + */ +public class MsoLocalClientNew implements MsoInterface { + + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoLocalClient.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + + @Override + public MsoResponseWrapper createSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception { + + String methodName = "createSvcInstance "; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + MsoResponseWrapper w = createInstance(requestDetails, ""); + + return w; + } + + public MsoResponseWrapper createInstance(RequestDetails request, String path) throws Exception { + String methodName = "createInstance"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + RestObject restObjStr = new RestObject(); + + String str = new String(); + + restObjStr.set(str); + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_create_instance_response.json"); + + restObjStr.setStatusCode(200); + restObjStr.set(IOUtils.toString(asdcServicesFile)); + + MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); + + return w; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + @Override + public MsoResponseWrapper createVnf(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String path) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper createVfModuleInstance(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper deleteSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper deleteVnf(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper deleteVfModule(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper deleteVolumeGroupInstance(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public MsoResponseWrapper deleteNwInstance(RequestDetails requestDetails, String endpoint) throws Exception { + return null; + } + + @Override + public void getOrchestrationRequest(String t, String sourceId, String endpoint, RestObject restObject) throws Exception { } + + @Override + public MsoResponseWrapper getOrchestrationRequestsForDashboard(String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + String methodName = "getOrchestrationRequestsForDashboard"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_get_orchestration_requests.json"); + + restObject.setStatusCode(200); + restObject.set(IOUtils.toString(asdcServicesFile)); + + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + + return w; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + public void activateServiceInstance(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception{ + String methodName = "activateServiceInstance"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_activate_service_instance.json"); + + restObject.setStatusCode(200); + restObject.set(IOUtils.toString(asdcServicesFile)); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + + @Override + public MsoResponseWrapper getManualTasksByRequestId(String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + String methodName = "getManualTasksByRequestId"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_get_manual_task_by_request_id.json"); + + restObject.setStatusCode(200); + restObject.set(IOUtils.toString(asdcServicesFile)); + + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + + return w; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + @Override + public MsoResponseWrapper completeManualTask(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + String methodName = "getManualTasksByRequestId"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + + final InputStream asdcServicesFile = MsoLocalClient.class.getClassLoader().getResourceAsStream("mso_complete_manual_task.json"); + + restObject.setStatusCode(200); + restObject.set(IOUtils.toString(asdcServicesFile)); + + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + + return w; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + @Override + public MsoResponseWrapper replaceVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String vnf_endpoint) throws Exception { + throw new NotImplementedException("Function was not implemented at this point."); + } + + + + @Override + public MsoResponseWrapper updateVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, + String vnf_endpoint) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoProperties.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoProperties.java index 272a2a2b8..0eed0e1d1 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoProperties.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoProperties.java @@ -24,7 +24,6 @@ import org.openecomp.portalsdk.core.util.SystemProperties; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Date; import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; /** @@ -35,10 +34,10 @@ public class MsoProperties extends SystemProperties { /** The Constant MSO_SERVER_URL. */ //VID Properties related to MSO public static final String MSO_SERVER_URL = "mso.server.url"; - + /** The Constant MSO_DME2_SERVER_URL. */ public static final String MSO_DME2_SERVER_URL = "mso.dme2.server.url"; - + /** The Constant MSO_DME2_CLIENT_TIMEOUT. */ public static final String MSO_DME2_CLIENT_TIMEOUT = "mso.dme2.client.timeout"; @@ -51,7 +50,7 @@ public class MsoProperties extends SystemProperties { /** The Constant MSO_POLLING_INTERVAL_MSECS. */ // number of msecs to wait between polling requests public static final String MSO_POLLING_INTERVAL_MSECS = "mso.polling.interval.msecs"; - + /** The Constant MSO_POLLING_INTERVAL_MSECS_DEFAULT. */ public static final String MSO_POLLING_INTERVAL_MSECS_DEFAULT = "60000"; @@ -68,14 +67,17 @@ public class MsoProperties extends SystemProperties { public static final String MSO_USER_NAME = "mso.user.name"; //m03346 /** The Constant MSO_PASSWORD. */ - public static final String MSO_PASSWORD = "mso.password.x"; + public static final String MSO_PASSWORD = "mso.password.x"; /** The Constant MSO_REST_API_SVC_INSTANCE. */ - public static final String MSO_REST_API_SVC_INSTANCE = "mso.restapi.svc.instance"; // /serviceInstances/v2 + public static final String MSO_REST_API_SVC_INSTANCE = "mso.restapi.svc.instance"; // /serviceInstances/v2 /** The Constant MSO_REST_API_VNF_INSTANCE. */ public static final String MSO_REST_API_VNF_INSTANCE = "mso.restapi.vnf.instance"; // /serviceInstances/v2/{service_instance_id}/vnfs + /** The Constant MSO_REST_API_VNF_CHANGE_MANAGEMENT_INSTANCE. */ + public static final String MSO_REST_API_VNF_CHANGE_MANAGEMENT_INSTANCE = "mso.restapi.vnf.changemanagement.instance"; // /serviceInstances/v2/{service_instance_id}/vnfs/{request_type} + /** The Constant MSO_REST_API_NETWORK_INSTANCE. */ public static final String MSO_REST_API_NETWORK_INSTANCE = "mso.restapi.network.instance"; // /serviceInstances/v2/{serviceInstanceId}/networks @@ -84,10 +86,13 @@ public class MsoProperties extends SystemProperties { /** The Constant MSO_REST_API_GET_ORC_REQS. */ public static final String MSO_REST_API_GET_ORC_REQS = "mso.restapi.get.orc.reqs"; - + + /** The Constant MSO_REST_API_GET_MAN_TASK. */ + public static final String MSO_REST_API_GET_MAN_TASKS = "mso.restapi.get.man.tasks"; + /** The Constant MSO_REST_API_VF_MODULE_INSTANCE. */ public static final String MSO_REST_API_VF_MODULE_INSTANCE = "mso.restapi.vf.module.instance"; - + /** The Constant MSO_REST_API_VOLUME_GROUP_INSTANCE. */ public static final String MSO_REST_API_VOLUME_GROUP_INSTANCE = "mso.restapi.volume.group.instance"; //serviceInstances/v2/{serviceInstanceId}/volumeGroups diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterface.java index f964b8353..5b331e908 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterface.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterface.java @@ -37,6 +37,7 @@ import org.openecomp.portalsdk.core.util.SystemProperties; import org.apache.commons.codec.binary.Base64; import org.eclipse.jetty.util.security.Password; +import org.openecomp.vid.changeManagement.ChangeManagementRequest; import org.openecomp.vid.client.HttpBasicClient; import org.openecomp.vid.client.HttpsBasicClient; import org.openecomp.vid.mso.rest.RequestDetails; @@ -57,7 +58,7 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc /** The common headers. */ private MultivaluedHashMap commonHeaders; - + /** * Instantiates a new mso rest interface. */ @@ -68,7 +69,7 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc /* (non-Javadoc) * @see org.openecomp.vid.mso.MsoRestInterfaceIfc#initRestClient() */ - public void initRestClient() + public void initMsoClient() { final String methodname = "initRestClient()"; @@ -131,7 +132,7 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); - initRestClient(); + initMsoClient(); final Response cres = client.target(url) .request() @@ -170,7 +171,7 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc logRequest (r); try { - initRestClient(); + initMsoClient(); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + " methodName sending request to: " + url); @@ -232,8 +233,64 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc logRequest (r); try { + + initMsoClient(); + + url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); + // Change the content length + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.header("content-length", 201) + //.header("X-FromAppId", sourceID) + .post(Entity.entity(r, MediaType.APPLICATION_JSON)); - initRestClient(); + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " No response entity, this is probably ok, e=" + + e.getMessage()); + } + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if ( status >= 200 && status <= 299 ) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + + } else { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with status="+status+", url="+url); + } + + } catch (Exception e) + { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } + + + /* (non-Javadoc) + * @see org.openecomp.vid.mso.MsoRestInterfaceIfc#Put(java.lang.Object, org.openecomp.vid.mso.rest.RequestDetails, java.lang.String, java.lang.String, org.openecomp.vid.mso.RestObject) + */ + @SuppressWarnings("unchecked") + public void Put(T t, ChangeManagementRequest r, String sourceID, String path, RestObject restObject) throws Exception { + + String methodName = "Put"; + String url=""; + + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " start"); + +// logRequest (r); + try { + + initMsoClient(); url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); @@ -244,7 +301,7 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc .headers(commonHeaders) //.header("content-length", 201) //.header("X-FromAppId", sourceID) - .post(Entity.entity(r, MediaType.APPLICATION_JSON)); + .put(Entity.entity(r, MediaType.APPLICATION_JSON)); try { t = (T) cres.readEntity(t.getClass()); @@ -287,7 +344,9 @@ public class MsoRestInterface extends MsoRestInt implements MsoRestInterfaceIfc public T getInstance(Class clazz) throws IllegalAccessException, InstantiationException { return clazz.newInstance(); - } + } + + } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceFactory.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceFactory.java index 8bb3093c1..ab12c7b14 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceFactory.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceFactory.java @@ -21,28 +21,24 @@ package org.openecomp.vid.mso; import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.mso.rest.MsoRestClientNew; /** * A factory for creating MsoRestInterface objects. */ public class MsoRestInterfaceFactory { - - /** - * Gets the single instance of MsoRestInterfaceFactory. - * - * @return single instance of MsoRestInterfaceFactory - */ - public static MsoRestInterfaceIfc getInstance () { - MsoRestInterfaceIfc obj = null; - -// String mso_dme2_enabled = SystemProperties.getProperty(MsoProperties.MSO_DME2_ENABLED); -// if ( (mso_dme2_enabled != null) && (mso_dme2_enabled.equalsIgnoreCase("true") ) ) { -// obj = new MsoDme2RestInterface(); -// } -// else { - obj = new MsoRestInterface(); -// } - return ( obj ); - } + /** + * Gets the single instance of MsoRestInterfaceFactory. + * + * @return single instance of MsoRestInterfaceFactory + */ + public static MsoInterface getInstance() { + String msoPropertyName = "mso.client.type"; + if (SystemProperties.containsProperty(msoPropertyName) && + SystemProperties.getProperty(msoPropertyName).equals("LOCAL")) { + return new MsoLocalClientNew(); + } else + return new MsoRestClientNew(); + } } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceIfc.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceIfc.java index 1a6dbcccb..4ff13eddd 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceIfc.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/MsoRestInterfaceIfc.java @@ -20,6 +20,7 @@ package org.openecomp.vid.mso; +import org.openecomp.vid.changeManagement.ChangeManagementRequest; import org.openecomp.vid.mso.rest.RequestDetails; /** @@ -30,7 +31,7 @@ public interface MsoRestInterfaceIfc { /** * Inits the rest client. */ - public void initRestClient(); + public void initMsoClient(); /** * Gets the. @@ -70,6 +71,18 @@ public interface MsoRestInterfaceIfc { */ public void Post(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception; + /** + * Put. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Put(T t, ChangeManagementRequest r, String sourceID, String path, RestObject restObject) throws Exception ; /*** * Log request. * diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/RestMsoImplementation.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/RestMsoImplementation.java new file mode 100644 index 000000000..ba0fdfaa8 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/RestMsoImplementation.java @@ -0,0 +1,326 @@ +package org.openecomp.vid.mso; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.codec.binary.Base64; +import org.eclipse.jetty.util.security.Password; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.changeManagement.MsoRequestDetails; +import org.openecomp.vid.client.HttpBasicClient; +import org.openecomp.vid.client.HttpsBasicClient; +import org.openecomp.vid.mso.rest.RequestDetails; +import org.openecomp.vid.mso.rest.RestInterface; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; + +/** + * Created by pickjonathan on 26/06/2017. + */ +public class RestMsoImplementation implements RestInterface { + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMsoImplementation.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** The client. */ + private static Client client = null; + + /** The common headers. */ + private MultivaluedHashMap commonHeaders; + /** + * Instantiates a new mso rest interface. + */ + + @Override + public void initMsoClient() + { + final String methodname = "initRestClient()"; + + final String username = SystemProperties.getProperty(MsoProperties.MSO_USER_NAME); + final String password = SystemProperties.getProperty(MsoProperties.MSO_PASSWORD); + final String mso_url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL); + final String decrypted_password = Password.deobfuscate(password); + + String authString = username + ":" + decrypted_password; + + byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); + String authStringEnc = new String(authEncBytes); + + commonHeaders = new MultivaluedHashMap(); + commonHeaders.put("Authorization", Collections.singletonList((Object) ("Basic " + authStringEnc))); + + boolean use_ssl = true; + if ( (mso_url != null) && ( !(mso_url.isEmpty()) ) ) { + if ( mso_url.startsWith("https")) { + use_ssl = true; + } + else { + use_ssl = false; + } + } + if (client == null) { + + try { + if ( use_ssl ) { + //logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + methodname + " getting HttpsBasicClient with username=" + username + // + " password=" + password); + client = HttpsBasicClient.getClient(); + } + else { + //logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + methodname + " getting HttpsBasicClient with username=" + username + // + " password=" + password); + client = HttpBasicClient.getClient(); + } + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + methodname + " Unable to get the SSL client"); + } + } + } + + public void Get (T t, String sourceId, String path, RestObject restObject ) throws Exception { + String methodName = "Get"; + + logger.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); + + String url=""; + restObject.set(t); + + url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); + + initMsoClient(); + + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .get(); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 200 || status == 202) { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + methodName + " REST api was successfull!"); + + } else { + throw new Exception(methodName + " with status="+ status + ", url= " + url ); + } + + logger.debug(EELFLoggerDelegate.debugLogger,methodName + " received status=" + status ); + + return; + } + + @Override + public void Delete(T t, RequestDetails r, String sourceID, String path, RestObject restObject) { + + String methodName = "Delete"; + String url=""; + Response cres = null; + + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " start"); + logRequest (r); + + try { + initMsoClient(); + + url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + " methodName sending request to: " + url); + + cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.entity(r) + .build("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)).invoke(); + // .method("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)); + //.delete(Entity.entity(r, MediaType.APPLICATION_JSON)); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 404) { // resource not found + String msg = "Resource does not exist...: " + cres.getStatus(); + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } else if (status == 200 || status == 204){ + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + "Resource " + url + " deleted"); + } else if (status == 202) { + String msg = "Delete in progress: " + status; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } + else { + String msg = "Deleting Resource failed: " + status; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " No response entity, this is probably ok, e=" + + e.getMessage()); + } + + } + catch (Exception e) + { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } + + @Override + public void Post(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception { + String methodName = "Post"; + String url=""; + + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " start"); + + logRequest (r); + try { + + initMsoClient(); + + url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); + // Change the content length + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.header("content-length", 201) + //.header("X-FromAppId", sourceID) + .post(Entity.entity(r, MediaType.APPLICATION_JSON)); + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " No response entity, this is probably ok, e=" + + e.getMessage()); + } + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if ( status >= 200 && status <= 299 ) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + + } else { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with status="+status+", url="+url); + } + + } catch (Exception e) + { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } + + @Override + public void logRequest(RequestDetails r) { + String methodName = "logRequest"; + ObjectMapper mapper = new ObjectMapper(); + String r_json_str = ""; + if ( r != null ) { + r_json_str = r.toString(); + try { + r_json_str = mapper.writeValueAsString(r); + } + catch ( com.fasterxml.jackson.core.JsonProcessingException j ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Unable to parse request as json"); + } + } + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Request=(" + r_json_str + ")"); + } + + @Override + public void logRequest(org.openecomp.vid.changeManagement.RequestDetails r) { + String methodName = "logRequest"; + ObjectMapper mapper = new ObjectMapper(); + String r_json_str = ""; + if ( r != null ) { + r_json_str = r.toString(); + try { + r_json_str = mapper.writeValueAsString(r); + } + catch ( com.fasterxml.jackson.core.JsonProcessingException j ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Unable to parse request as json"); + } + } + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Request=(" + r_json_str + ")"); + } + + @Override + public void Put(T t, org.openecomp.vid.changeManagement.RequestDetailsWrapper r, String sourceID, String path, RestObject restObject) throws Exception { + + String methodName = "Put"; + String url=""; + + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " start"); + +// logRequest (r); + try { + + initMsoClient(); + + url = SystemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); + // Change the content length + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.header("content-length", 201) + //.header("X-FromAppId", sourceID) + .put(Entity.entity(r, MediaType.APPLICATION_JSON)); + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " No response entity, this is probably ok, e=" + + e.getMessage()); + } + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if ( status >= 200 && status <= 299 ) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " REST api POST was successful!"); + + } else { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with status="+status+", url="+url); + } + + } catch (Exception e) + { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoBusinessLogicNew.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoBusinessLogicNew.java new file mode 100644 index 000000000..1afb2df21 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoBusinessLogicNew.java @@ -0,0 +1,67 @@ +package org.openecomp.vid.mso.rest; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.mso.MsoClientFactory; +import org.openecomp.vid.mso.MsoInterface; +import org.openecomp.vid.mso.MsoResponseWrapper; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by pickjonathan on 21/06/2017. + * This class was created only for testing the new logic. + * It is not used by any of the controllers binded to the ui. + * This can be deleted in the future in order to keep a cleaner project. + * If deleting please dont forget to delete the controllers, factory and all involved in the assert test. + */ +public class MsoBusinessLogicNew { + + /** + * \ + * The MSO Client + */ + private MsoInterface msoClient; + + private MsoInterface msoRestTempClient; + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoBusinessLogicNew.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + public MsoBusinessLogicNew() { + msoClient = MsoClientFactory.getInstance(); + msoRestTempClient = new MsoRestClientNew(); + } + + public MsoResponseWrapper createSvcInstance(RequestDetails msoRequest) throws Exception { + String methodName = "createSvcInstance "; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + +// String endpoint = SystemProperties.getProperty(MsoProperties.MSO_REST_API_SVC_INSTANCE); +// +// MsoResponseWrapper w = createInstance(msoRequest, p); + + MsoResponseWrapper w = msoClient.createSvcInstance(msoRequest, ""); + + return w; + } + + + public MsoResponseWrapper createSvcInstanceRest(RequestDetails msoRequest) throws Exception { + String methodName = "createSvcInstance "; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + + MsoResponseWrapper w = msoRestTempClient.createSvcInstance(msoRequest, ""); + + return w; + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoRestClientNew.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoRestClientNew.java new file mode 100644 index 000000000..1beeafb13 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/MsoRestClientNew.java @@ -0,0 +1,333 @@ +package org.openecomp.vid.mso.rest; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.changeManagement.MsoRequestDetails; +import org.openecomp.vid.changeManagement.RequestDetailsWrapper; +import org.openecomp.vid.mso.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + + +/** + * Created by pickjonathan on 21/06/2017. + */ +public class MsoRestClientNew extends RestMsoImplementation implements MsoInterface { + + /** + * The logger. + */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MsoRestClientNew.class); + + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + private final String ORIGINAL_REQUEST_ID = "originalRequestId"; + + + @Override + public MsoResponseWrapper createSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "createSvcInstance "; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return createInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper createVnf(RequestDetails requestDetails, String endpoint) throws Exception { + + String methodName = "createVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return createInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String endpoint) throws Exception { + + String methodName = "createNwInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return createInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "createVolumeGroupInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return createInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper createVfModuleInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "createVfModuleInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return createInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper deleteSvcInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "deleteSvcInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return deleteInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper deleteVnf(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "deleteVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return deleteInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper deleteVfModule(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "deleteVfModule"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return deleteInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper deleteVolumeGroupInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "deleteVolumeGroupInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return deleteInstance(requestDetails, endpoint); + } + + @Override + public MsoResponseWrapper deleteNwInstance(RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "deleteNwInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return deleteInstance(requestDetails, endpoint); + } + + @Override + public void getOrchestrationRequest(String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + Get(t, sourceId, endpoint, restObject); + } + + public void getManualTasks(String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + Get(t, sourceId, endpoint, restObject); + } + + + public MsoResponseWrapper createInstance(RequestDetails request, String path) throws Exception { + String methodName = "createInstance"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + RestObject restObjStr = new RestObject(); + + String str = new String(); + + restObjStr.set(str); + + Post(str, request, "", path, restObjStr); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); + + return w; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + + /** + * Delete instance. + * + * @param request the request + * @param path the path + * @return the mso response wrapper + * @throws Exception the exception + */ + public MsoResponseWrapper deleteInstance(RequestDetails request, String path) throws Exception { + String methodName = "deleteInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Delete, path =[" + path + "]"); + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + Delete(str, request, "", path, restObjStr); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + return w; + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + + } + + public MsoResponseWrapper getOrchestrationRequestsForDashboard(String t, String sourceId, String endpoint, RestObject restObject) throws Exception{ + String methodName = "getOrchestrationRequestsForDashboard"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + getOrchestrationRequest(t, sourceId, endpoint, restObject); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + + return w; + + } catch (Exception e){ + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + public MsoResponseWrapper getManualTasksByRequestId(String t , String sourceId , String endpoint , RestObject restObject) throws Exception{ + String methodName = "getManualTasksByRequestId"; + logger.debug(dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + getManualTasks(t , sourceId , endpoint , restObject); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + + return MsoUtil.wrapResponse(restObject); + + } catch (Exception e){ + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + + + @Override + public MsoResponseWrapper completeManualTask(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception { + String methodName = "completeManualTask"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Complete "); + try { + + Post(t, requestDetails , sourceId, endpoint, restObject); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + return w; + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + + @Override + public MsoResponseWrapper replaceVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "replaceVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + return replaceInstance(requestDetails, endpoint); + } + + public MsoResponseWrapper replaceInstance(org.openecomp.vid.changeManagement.RequestDetails request, String path) throws Exception { + String methodName = "replaceInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Replace VNF, path =[" + path + "]"); + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper(); + requestDetailsWrapper.requestDetails = new MsoRequestDetails(request); + + Post(str, request, "", path, restObjStr); + MsoResponseWrapper msoResponseWrapperObject = MsoUtil.wrapResponse(restObjStr); + int status = msoResponseWrapperObject.getStatus(); + if (status == 202){ + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + + ",post succeeded, msoResponseWrapperObject response:" + msoResponseWrapperObject.getResponse()); + } + else { + logger.error(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + + ": post failed, msoResponseWrapperObject status" + status + ", response:" + msoResponseWrapperObject.getResponse()); + + // TODO + } + return msoResponseWrapperObject; + + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + + } + + @Override + public MsoResponseWrapper updateVnf(org.openecomp.vid.changeManagement.RequestDetails requestDetails, String endpoint) throws Exception { + String methodName = "updateVnf"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + RequestDetailsWrapper wrapper = new RequestDetailsWrapper(); + wrapper.requestDetails = new MsoRequestDetails(requestDetails);; + return updateInstance(requestDetails, endpoint); + } + + public MsoResponseWrapper updateInstance(org.openecomp.vid.changeManagement.RequestDetails request, String path) throws Exception { + String methodName = "updateInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start"); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " calling Delete, path =[" + path + "]"); + + RestObject restObjStr = new RestObject(); + String str = new String(); + restObjStr.set(str); + RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper(); + requestDetailsWrapper.requestDetails = new MsoRequestDetails(request); + + + + Put(str, requestDetailsWrapper, "", path, restObjStr); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObjStr); + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w=" + w.getResponse()); + return w; + + } catch (Exception e) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + + } + + public void activateServiceInstance(RequestDetails requestDetails, String t, String sourceId, String endpoint, RestObject restObject) throws Exception{ + String methodName = "activateServiceInstance"; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " start "); + try { + + Post(t, requestDetails , sourceId, endpoint, restObject); + MsoResponseWrapper w = MsoUtil.wrapResponse(restObject); + + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " w =" + w.getResponse()); + + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "." + methodName + e.toString()); + throw e; + } + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RelatedModel.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RelatedModel.java index dc67a9456..427d71dd1 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RelatedModel.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RelatedModel.java @@ -46,6 +46,10 @@ public class RelatedModel extends org.openecomp.vid.domain.mso.RelatedModel { /** (Required). */ @JsonProperty("modelInfo") private org.openecomp.vid.domain.mso.ModelInfo modelInfo; + +// /** The related model object instance list. */ +// @JsonProperty("instanceId") +// private org.openecomp.vid.domain.mso.InstanceIds instanceId; /** The additional properties. */ @JsonIgnore diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestDetails.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestDetails.java index 6e7c5af32..0cf697e0b 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestDetails.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestDetails.java @@ -65,7 +65,7 @@ public class RequestDetails extends org.openecomp.vid.domain.mso.RequestDetails /** The related model list. */ @JsonProperty("relatedModelList") - private List relatedModelList; + private List relatedInstanceList; /** The request info. */ @JsonProperty("requestInfo") @@ -122,25 +122,24 @@ public class RequestDetails extends org.openecomp.vid.domain.mso.RequestDetails public void setModelInfo(ModelInfo modelInfo) { this.modelInfo = modelInfo; } - /** - * Gets the related model list. + * Gets the related instance list. * - * @return The relatedModelList + * @return The relatedInstanceList */ - @JsonProperty("relatedModelList") - public List getRelatedModelList() { - return relatedModelList; + @JsonProperty("relatedInstanceList") + public List getRelatedInstanceList() { + return relatedInstanceList; } /** * Sets the related model list. * - * @param relatedModelList The relatedModelList + * @param relatedInstanceList The relatedInstanceList */ - @JsonProperty("relatedModelList") - public void setRelatedModelList( List relatedModelList) { - this.relatedModelList = relatedModelList; + @JsonProperty("relatedInstanceList") + public void setRelatedInstanceList( List relatedInstanceList) { + this.relatedInstanceList = relatedInstanceList; } /** @@ -212,7 +211,7 @@ public class RequestDetails extends org.openecomp.vid.domain.mso.RequestDetails */ @Override public int hashCode() { - return new HashCodeBuilder().append(cloudConfiguration).append(modelInfo).append(relatedModelList).append(requestInfo).append(getRequestParameters()).append(subscriberInfo).append(additionalProperties).toHashCode(); + return new HashCodeBuilder().append(cloudConfiguration).append(modelInfo).append(relatedInstanceList).append(requestInfo).append(getRequestParameters()).append(subscriberInfo).append(additionalProperties).toHashCode(); } /* (non-Javadoc) @@ -227,7 +226,7 @@ public class RequestDetails extends org.openecomp.vid.domain.mso.RequestDetails return false; } RequestDetails rhs = ((RequestDetails) other); - return new EqualsBuilder().append(cloudConfiguration, rhs.cloudConfiguration).append(modelInfo, rhs.modelInfo).append(relatedModelList, rhs.relatedModelList).append(requestInfo, rhs.requestInfo).append(getRequestParameters(), rhs.getRequestParameters()).append(subscriberInfo, rhs.subscriberInfo).append(additionalProperties, rhs.additionalProperties).isEquals(); + return new EqualsBuilder().append(cloudConfiguration, rhs.cloudConfiguration).append(modelInfo, rhs.modelInfo).append(relatedInstanceList, rhs.relatedInstanceList).append(requestInfo, rhs.requestInfo).append(getRequestParameters(), rhs.getRequestParameters()).append(subscriberInfo, rhs.subscriberInfo).append(additionalProperties, rhs.additionalProperties).isEquals(); } } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestList.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestList.java index 7c366ac82..8a57c74b7 100755 --- a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestList.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestList.java @@ -58,7 +58,7 @@ import java.util.List; public class RequestList { /** The request list. */ - private List requestList; + private List requestList; /** The additional properties. */ @JsonIgnore @@ -69,7 +69,7 @@ public class RequestList { * * @return The RelatedModel List */ - public List getRequestList() { + public List getRequestList() { return requestList; } @@ -78,7 +78,7 @@ public class RequestList { * * @param l the new request list */ - public void setRequestList(List l) { + public void setRequestList(List l) { this.requestList = l; } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestWrapper.java new file mode 100644 index 000000000..b0e9fa125 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RequestWrapper.java @@ -0,0 +1,35 @@ +package org.openecomp.vid.mso.rest; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * request wrapper structure. + */ +public class RequestWrapper { + + + /** The request. */ + private Request request; + + + /** + * Gets the request. + * + * @return The requestDetails + */ + @JsonProperty("request") + public Request getRequest() { + return request; + } + + /** + * Sets the request. + * + * @param request The request + */ + @JsonProperty + public void setRequest(Request request) { + this.request = request; + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Response.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Response.java new file mode 100644 index 000000000..ee3a8bfef --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Response.java @@ -0,0 +1,54 @@ +package org.openecomp.vid.mso.rest; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Response { + + /** The status. */ + private int status; + + /** The entity. */ + private RequestList entity; + + /** + * Gets the status. + * + * @return The status + */ + @JsonProperty("status") + public int getStatus() { + return status; + } + + /** + * Sets the status. + * + * @param status The status + */ + @JsonProperty("status") + public void setStatus(int status) { + this.status = status; + } + + /** + * Gets the entity. + * + * @return The entity + */ + @JsonProperty("entity") + public RequestList getEntity() { + return entity; + } + + /** + * Sets the entity. + * + * @param entity The entity + */ + @JsonProperty("entity") + public void setEntity(RequestList entity) { + this.entity = entity; + } + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RestInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RestInterface.java new file mode 100644 index 000000000..1e2733587 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/RestInterface.java @@ -0,0 +1,81 @@ +package org.openecomp.vid.mso.rest; + +import org.openecomp.vid.mso.RestObject; + +/** + * Created by pickjonathan on 26/06/2017. + */ +public interface RestInterface { + + /** + * Inits the rest client. + */ + public void initMsoClient(); + + /** + * Gets the. + * + * @param the generic type + * @param t the t + * @param sourceId the source id + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Get (T t, String sourceId, String path, RestObject restObject ) throws Exception; + + /** + * Delete. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Delete(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception; + + /** + * Post. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Post(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception; + + /** + * Put. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Put(T t, org.openecomp.vid.changeManagement.RequestDetailsWrapper r, String sourceID, String path, RestObject restObject) throws Exception; + + + /*** + * Log request. + * + * @param r the r + */ + public void logRequest ( RequestDetails r ); + /*** + * Log request. + * + * @param r the r + */ + public void logRequest(org.openecomp.vid.changeManagement.RequestDetails r); + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Task.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Task.java new file mode 100644 index 000000000..8d72890ff --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/Task.java @@ -0,0 +1,119 @@ +package org.openecomp.vid.mso.rest; + +import java.util.List; + +public class Task { + + private String taskId; + private String type; + private String nfRole; + private String subscriptionServiceType; + private String originalRequestId; + private String originalRequestorId; + private String errorSource; + private String errorCode; + private String errorMessage; + private String buildingBlockName; + private String buildingBlockStep; + private List validResponses; + + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getNfRole() { + return nfRole; + } + + public void setNfRole(String nfRole) { + this.nfRole = nfRole; + } + + public String getSubscriptionServiceType() { + return subscriptionServiceType; + } + + public void setSubscriptionServiceType(String subscriptionServiceType) { + this.subscriptionServiceType = subscriptionServiceType; + } + + public String getOriginalRequestId() { + return originalRequestId; + } + + public void setOriginalRequestId(String originalRequestId) { + this.originalRequestId = originalRequestId; + } + + public String getOriginalRequestorId() { + return originalRequestorId; + } + + public void setOriginalRequestorId(String originalRequestorId) { + this.originalRequestorId = originalRequestorId; + } + + public String getErrorSource() { + return errorSource; + } + + public void setErrorSource(String errorSource) { + this.errorSource = errorSource; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public String getBuildingBlockName() { + return buildingBlockName; + } + + public void setBuildingBlockName(String buildingBlockName) { + this.buildingBlockName = buildingBlockName; + } + + public String getBuildingBlockStep() { + return buildingBlockStep; + } + + public void setBuildingBlockStep(String buildingBlockStep) { + this.buildingBlockStep = buildingBlockStep; + } + + public List getValidResponses() { + return validResponses; + } + + public void setValidResponses(List validResponses) { + this.validResponses = validResponses; + } + + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/TaskList.java b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/TaskList.java new file mode 100644 index 000000000..7232364a3 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/mso/rest/TaskList.java @@ -0,0 +1,16 @@ +package org.openecomp.vid.mso.rest; + +import java.util.List; + +public class TaskList { + + public List getTaskList() { + return taskList; + } + + public void setTaskList(List taskList) { + this.taskList = taskList; + } + + private List taskList; +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyProperties.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyProperties.java new file mode 100644 index 000000000..d273aa6a7 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyProperties.java @@ -0,0 +1,26 @@ +package org.openecomp.vid.policy; + +import org.openecomp.portalsdk.core.util.SystemProperties; + + +public class PolicyProperties extends SystemProperties { + + public static final String POLICY_CLIENTAUTH_VAL = "policy.ClientAuth"; + + public static final String POLICY_CLIENT_MECHID_VAL = "policy.client.mechId"; + + public static final String POLICY_CLIENT_PASSWORD_VAL = "policy.client.password"; + + public static final String POLICY_USERNAME_VAL = "policy.username"; + + public static final String POLICY_PASSWORD_VAL = "policy.password"; + + public static final String POLICY_AUTHORIZATION_VAL = "policy.Authorization"; + + public static final String POLICY_SERVER_URL_VAL = "policy.server.url"; + + public static final String POLICY_ENVIRONMENT_VAL = "policy.environment"; + + public static final String POLICY_GET_CONFIG_VAL = "policy.get.config"; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyResponseWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyResponseWrapper.java new file mode 100644 index 000000000..02ca0f0ec --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyResponseWrapper.java @@ -0,0 +1,56 @@ +package org.openecomp.vid.policy; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * This wrapper encapsulates the Policy response + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "status", + "entity" +}) + +public class PolicyResponseWrapper { + + @JsonProperty("status") + private int status; + + @JsonProperty("entity") + private String entity; + + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + @JsonProperty("status") + public int getStatus() { + return status; + } + + @JsonProperty("status") + public void setStatus(int v) { + this.status = v; + } + + @JsonProperty("entity") + public void setEntity(String v) { + this.entity = v; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String getResponse () { + + StringBuilder b = new StringBuilder ("{ \"status\": "); + b.append(getStatus()).append(", \"entity\": " ).append(this.getEntity()).append("}"); + return (b.toString()); + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInt.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInt.java new file mode 100644 index 000000000..7c075a535 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInt.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.policy; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.policy.rest.RequestDetails; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PolicyRestInt { + + /** The logger. */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PolicyRestInterface.class); + + /** The Constant dateFormat. */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** The request date format. */ + public DateFormat requestDateFormat = new SimpleDateFormat("EEE, dd MMM YYYY HH:mm:ss z"); + + public PolicyRestInt() { + requestDateFormat.setTimeZone(java.util.TimeZone.getTimeZone("GMT")); + } + + /** + * Log request. + * + * @param r the r + */ + public void logRequest ( RequestDetails r ) { + String methodName = "logRequest"; + ObjectMapper mapper = new ObjectMapper(); + String r_json_str = ""; + if ( r != null ) { + r_json_str = r.toString(); + try { + r_json_str = mapper.writeValueAsString(r); + } + catch ( com.fasterxml.jackson.core.JsonProcessingException j ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Unable to parse request as json"); + } + } + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Request=(" + r_json_str + ")"); + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterface.java new file mode 100644 index 000000000..d6a59da20 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterface.java @@ -0,0 +1,234 @@ +package org.openecomp.vid.policy; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; + +import org.apache.commons.codec.binary.Base64; +import org.eclipse.jetty.util.security.Password; +import org.json.simple.JSONObject; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.client.HttpBasicClient; +import org.openecomp.vid.policy.rest.RequestDetails; + +public class PolicyRestInterface extends PolicyRestInt implements PolicyRestInterfaceIfc { + + /** The logger. */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PolicyRestInterface.class); + + /** The Constant dateFormat. */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** The client. */ + private static Client client = null; + + /** The common headers. */ + private MultivaluedHashMap commonHeaders; + + public PolicyRestInterface() { + super(); + } + + public void initRestClient() + { + final String methodname = "initRestClient()"; + + //final String clientAuth = SystemProperties.getProperty(PolicyProperties.POLICY_CLIENTAUTH_VAL); + //final String authorization = SystemProperties.getProperty(PolicyProperties.POLICY_AUTHORIZATION_VAL); + final String mechId = SystemProperties.getProperty(PolicyProperties.POLICY_CLIENT_MECHID_VAL); + final String clientPassword = SystemProperties.getProperty(PolicyProperties.POLICY_CLIENT_PASSWORD_VAL); + final String username = SystemProperties.getProperty(PolicyProperties.POLICY_USERNAME_VAL); + final String password = SystemProperties.getProperty(PolicyProperties.POLICY_PASSWORD_VAL); + final String environment = SystemProperties.getProperty(PolicyProperties.POLICY_ENVIRONMENT_VAL); + + final String decrypted_client_password = Password.deobfuscate(clientPassword); + String mechAuthString = mechId + ":" + decrypted_client_password; + byte[] mechAuthEncBytes = Base64.encodeBase64(mechAuthString.getBytes()); + String clientAuth = new String(mechAuthEncBytes); + + final String decrypted_password = Password.deobfuscate(password); + String authString = username + ":" + decrypted_password; + byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); + String authorization = new String(authEncBytes); + + commonHeaders = new MultivaluedHashMap (); + commonHeaders.put("ClientAuth", Collections.singletonList((Object) ("Basic " + clientAuth))); + commonHeaders.put("Authorization", Collections.singletonList((Object) ("Basic " + authorization))); + commonHeaders.put("Environment", Collections.singletonList((Object) (environment))); + + if (client == null) { + + try { + client = HttpBasicClient.getClient(); + } catch (Exception e) { + System.out.println( methodname + " Unable to get the SSL client"); + } + } + } + + @SuppressWarnings("unchecked") + public void Get (T t, String sourceId, String path, RestObject restObject ) throws Exception { + String methodName = "Get"; + + logger.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); + + String url=""; + restObject.set(t); + + url = SystemProperties.getProperty(PolicyProperties.POLICY_SERVER_URL_VAL) + path; + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " sending request to url= " + url); + + initRestClient(); + + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .get(); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 200) { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + methodName + " REST api was successfull!"); + + } else { + throw new Exception(methodName + " with status="+ status + ", url= " + url ); + } + + logger.debug(EELFLoggerDelegate.debugLogger,methodName + " received status=" + status ); + + return; + } + + @SuppressWarnings("unchecked") + public void Delete(T t, RequestDetails r, String sourceID, String path, RestObject restObject) { + + String methodName = "Delete"; + String url=""; + Response cres = null; + + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " start"); + logRequest (r); + + try { + initRestClient(); + + url = SystemProperties.getProperty(PolicyProperties.POLICY_SERVER_URL_VAL) + path; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + " methodName sending request to: " + url); + + cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.entity(r) + .build("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)).invoke(); + // .method("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)); + //.delete(Entity.entity(r, MediaType.APPLICATION_JSON)); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 404) { // resource not found + String msg = "Resource does not exist...: " + cres.getStatus(); + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } else if (status == 200 || status == 204){ + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + "Resource " + url + " deleted"); + } else if (status == 202) { + String msg = "Delete in progress: " + status; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } + else { + String msg = "Deleting Resource failed: " + status; + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + msg); + } + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " No response entity, this is probably ok, e=" + + e.getMessage()); + } + + } + catch (Exception e) + { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } + + @SuppressWarnings("unchecked") + public void Post(T t, JSONObject requestDetails, String uuid, String path, RestObject restObject) throws Exception { + + String methodName = "Post"; + String url=""; + + System.out.println( "POST policy rest interface"); + + // logRequest (requestDetails); + try { + + initRestClient(); + + url = SystemProperties.getProperty(PolicyProperties.POLICY_SERVER_URL_VAL) + path; + System.out.println( "<== " + methodName + " sending request to url= " + url); + // Change the content length + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.header("content-length", 201) + //.header("X-FromAppId", sourceID) + .post(Entity.entity(requestDetails, MediaType.APPLICATION_JSON)); + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + + System.out.println("<== " + methodName + " No response entity, this is probably ok, e=" + e.getMessage()); + } + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if ( status >= 200 && status <= 299 ) { + System.out.println( "<== " + methodName + " REST api POST was successful!"); + + } else { + System.out.println( "<== " + methodName + " with status="+status+", url="+url); + } + + } catch (Exception e) + { + System.out.println( "<== " + methodName + " with url="+url+ ", Exception: " + e.toString()); + throw e; + + } + } + + public T getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + + @Override + public void logRequest(RequestDetails r) { + // TODO Auto-generated method stub + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceFactory.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceFactory.java new file mode 100644 index 000000000..1570875c0 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceFactory.java @@ -0,0 +1,14 @@ + +package org.openecomp.vid.policy; + +public class PolicyRestInterfaceFactory { + + + public static PolicyRestInterfaceIfc getInstance () { + PolicyRestInterfaceIfc obj = null; + + obj = new PolicyRestInterface(); + + return ( obj ); + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceIfc.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceIfc.java new file mode 100644 index 000000000..f56924b36 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyRestInterfaceIfc.java @@ -0,0 +1,58 @@ + +package org.openecomp.vid.policy; + +import org.json.simple.JSONObject; +import org.openecomp.vid.policy.rest.RequestDetails; + +public interface PolicyRestInterfaceIfc { + /** + * Inits the rest client. + */ + public void initRestClient(); + + /** + * Gets the. + * + * @param the generic type + * @param t the t + * @param sourceId the source id + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Get (T t, String sourceId, String path, RestObject restObject ) throws Exception; + + /** + * Delete. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Delete(T t, RequestDetails r, String sourceID, String path, RestObject restObject) throws Exception; + + /** + * Post. + * + * @param the generic type + * @param t the t + * @param r the r + * @param sourceID the source ID + * @param path the path + * @param restObject the rest object + * @throws Exception the exception + */ + public void Post(T t, JSONObject r, String sourceID, String path, RestObject restObject) throws Exception; + + /*** + * Log request. + * + * @param r the r + */ + public void logRequest ( RequestDetails r ); + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyUtil.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyUtil.java new file mode 100644 index 000000000..ceda7c427 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/PolicyUtil.java @@ -0,0 +1,71 @@ +package org.openecomp.vid.policy; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.glassfish.jersey.client.ClientResponse; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.policy.PolicyResponseWrapper; +import org.openecomp.vid.policy.PolicyUtil; +import org.openecomp.vid.policy.RestObject; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PolicyUtil { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(PolicyUtil.class); + + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + public static PolicyResponseWrapper wrapResponse ( String body, int statusCode ) { + + PolicyResponseWrapper w = new PolicyResponseWrapper(); + w.setStatus (statusCode); + w.setEntity(body); + + return w; + } + + public static PolicyResponseWrapper wrapResponse (ClientResponse cres) { + String resp_str = ""; + if ( cres != null ) { + resp_str = cres.readEntity(String.class); + } + int statuscode = cres.getStatus(); + PolicyResponseWrapper w = PolicyUtil.wrapResponse ( resp_str, statuscode ); + return (w); + } + + public static PolicyResponseWrapper wrapResponse (RestObject rs) { + String resp_str = ""; + int status = 0; + if ( rs != null ) { + resp_str = rs.get(); + status = rs.getStatusCode(); + } + PolicyResponseWrapper w = PolicyUtil.wrapResponse ( resp_str, status ); + return (w); + } + + public static String convertPojoToString ( T t ) throws com.fasterxml.jackson.core.JsonProcessingException { + + String methodName = "convertPojoToString"; + ObjectMapper mapper = new ObjectMapper(); + String r_json_str = ""; + if ( t != null ) { + try { + r_json_str = mapper.writeValueAsString(t); + } + catch ( com.fasterxml.jackson.core.JsonProcessingException j ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Unable to parse object as json"); + } + } + return (r_json_str); + } + + + public static void main(String[] args) { + // TODO Auto-generated method stub + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/RestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/RestObject.java new file mode 100644 index 000000000..de085f24b --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/RestObject.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.policy; + +/** + * The Class RestObject. + * + * @param the generic type + */ +public class RestObject { + + /** + * Generic version of the RestObject class. + * + */ + // T stands for "Type" + private T t; + + /** The status code. */ + private int statusCode= 0; + + /** + * Sets the. + * + * @param t the t + */ + public void set(T t) { this.t = t; } + + /** + * Gets the. + * + * @return the t + */ + public T get() { return t; } + + /** + * Sets the status code. + * + * @param v the new status code + */ + public void setStatusCode(int v) { this.statusCode = v; } + + /** + * Gets the status code. + * + * @return the status code + */ + public int getStatusCode() { return this.statusCode; } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/policy/rest/RequestDetails.java b/vid-app-common/src/main/java/org/openecomp/vid/policy/rest/RequestDetails.java new file mode 100644 index 000000000..93e80d6b3 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/policy/rest/RequestDetails.java @@ -0,0 +1,107 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.policy.rest; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +/* + [ + { + "policyConfigMessage": "Config Retrieved! ", + "policyConfigStatus": "CONFIG_RETRIEVED", + "type": "JSON", + "config": "{\"service\":\"TimeLimitAndVerticalTopology\",\"policyName\":\"SNIRO_CM_1707.Demo_TimeLimitAndVerticalTopology_zone_localTime\",\"description\":\"dev instance\",\"templateVersion\":\"1702.03\",\"version\":\"1707\",\"priority\":\"4\",\"riskType\":\"test\",\"riskLevel\":\"3\",\"guard\":\"False\",\"content\":{\"serviceType\":\"networkOnDemand\",\"identity\":\"vnf_upgrade_policy\",\"policyScope\":{\"serviceType\":[\"networkOnDemand\"],\"aicZone\":[\" \"],\"entityType\":[\"vnf\"]},\"timeSchedule\":{\"allowedPeriodicTime\":[{\"day\":\"weekday\",\"timeRange\":[{\"start_time\":\"04:00:00\",\"end_time\":\"13:00:00\"}]}]},\"nodeType\":[\"vnf\"],\"type\":\"timeLimitAndVerticalTopology\",\"conflictScope\":\"vnf_zone\"}}", + "policyName": "SNIRO_CM_1707.Config_MS_Demo_TimeLimitAndVerticalTopology_zone_localTime.1.xml", + "policyVersion": "1", + "matchingConditions": { + "ECOMPName": "SNIRO-Placement", + "ConfigName": "", + "service": "TimeLimitAndVerticalTopology", + "uuid": "", + "Location": "" + }, + "responseAttributes": {}, + "property": null + }, + { + "policyConfigMessage": "Config Retrieved! ", + "policyConfigStatus": "CONFIG_RETRIEVED", + "type": "JSON", + "config": "{\"service\":\"TimeLimitAndVerticalTopology\",\"policyName\":\"SNIRO_CM_1707.Demo_TimeLimitAndVerticalTopology_pserver_localTime\",\"description\":\"dev instance\",\"templateVersion\":\"1702.03\",\"version\":\"1707\",\"priority\":\"4\",\"riskType\":\"test\",\"riskLevel\":\"3\",\"guard\":\"False\",\"content\":{\"serviceType\":\"networkOnDemand\",\"identity\":\"vnf_upgrade_policy\",\"policyScope\":{\"serviceType\":[\"networkOnDemand\"],\"aicZone\":[\" \"],\"entityType\":[\"vnf\"]},\"timeSchedule\":{\"allowedPeriodicTime\":[{\"day\":\"weekday\",\"timeRange\":[{\"start_time\":\"04:00:00\",\"end_time\":\"13:00:00\"}]}]},\"nodeType\":[\"vnf\"],\"type\":\"timeLimitAndVerticalTopology\",\"conflictScope\":\"vnf_pserver\"}}", + "policyName": "SNIRO_CM_1707.Config_MS_Demo_TimeLimitAndVerticalTopology_pserver_localTime.1.xml", + "policyVersion": "1", + "matchingConditions": { + "ECOMPName": "SNIRO-Placement", + "ConfigName": "", + "service": "TimeLimitAndVerticalTopology", + "uuid": "", + "Location": "" + }, + "responseAttributes": {}, + "property": null + }, + { + "policyConfigMessage": "Config Retrieved! ", + "policyConfigStatus": "CONFIG_RETRIEVED", + "type": "JSON", + "config": "{\"service\":\"TimeLimitAndVerticalTopology\",\"policyName\":\"SNIRO_CM_1707.Demo_TimeLimitAndVerticalTopology_vnf_localTime\",\"description\":\"dev instance\",\"templateVersion\":\"1702.03\",\"version\":\"1707\",\"priority\":\"4\",\"riskType\":\"test\",\"riskLevel\":\"3\",\"guard\":\"False\",\"content\":{\"serviceType\":\"networkOnDemand\",\"identity\":\"vnf_upgrade_policy\",\"policyScope\":{\"serviceType\":[\"networkOnDemand\"],\"aicZone\":[\" \"],\"entityType\":[\"vnf\"]},\"timeSchedule\":{\"allowedPeriodicTime\":[{\"day\":\"weekday\",\"timeRange\":[{\"start_time\":\"04:00:00\",\"end_time\":\"13:00:00\"}]}]},\"nodeType\":[\"vnf\"],\"type\":\"timeLimitAndVerticalTopology\",\"conflictScope\":\"vnf\"}}", + "policyName": "SNIRO_CM_1707.Config_MS_Demo_TimeLimitAndVerticalTopology_vnf_localTime.1.xml", + "policyVersion": "1", + "matchingConditions": { + "ECOMPName": "SNIRO-Placement", + "ConfigName": "", + "service": "TimeLimitAndVerticalTopology", + "uuid": "", + "Location": "" + }, + "responseAttributes": {}, + "property": null + } + ] +*/ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "policyConfigMessage", + "policyConfigStatus", + "type", + "config", + "policyName", + "policyVersion", + "matchingConditions" +}) +public class RequestDetails { + + @JsonProperty("policyName") + private String policyName; + + @JsonProperty("policyName") + public String getPolicyName() { + return policyName; + } + + @JsonProperty("policyName") + public void setPolicyName(String policyName) { + this.policyName = policyName; + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/properties/MsoClientConfiguration.java b/vid-app-common/src/main/java/org/openecomp/vid/properties/MsoClientConfiguration.java new file mode 100644 index 000000000..f7a331a7e --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/properties/MsoClientConfiguration.java @@ -0,0 +1,9 @@ +package org.openecomp.vid.properties; + +/** + * Created by pickjonathan on 20/06/2017. + */ +public class MsoClientConfiguration { + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/roles/Role.java b/vid-app-common/src/main/java/org/openecomp/vid/roles/Role.java index d4ded5303..f818e48fa 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/roles/Role.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/roles/Role.java @@ -1,9 +1,9 @@ package org.openecomp.vid.roles; - /** * Created by Oren on 7/1/17. */ + public class Role { private EcompRole ecompRole; diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObject.java new file mode 100644 index 000000000..57b36830e --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObject.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.scheduler; + + +public class RestObject { + + private T t; + + private int statusCode= 0; + + public String uuid; + + public void set(T t) { this.t = t; } + + public T get() { return t; } + + public void setStatusCode(int v) { this.statusCode = v; } + + public int getStatusCode() { return this.statusCode; } + + public void setUUID(String uuid) { this.uuid = uuid; } + + public String getUUID() { return this.uuid; } +} + diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/GetTimeSlotsRestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/GetTimeSlotsRestObject.java new file mode 100644 index 000000000..614b557a0 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/GetTimeSlotsRestObject.java @@ -0,0 +1,11 @@ +package org.openecomp.vid.scheduler.RestObjects; + +public class GetTimeSlotsRestObject extends org.openecomp.vid.scheduler.RestObject { + + public String uuid; + + public void setUUID(String uuid) { this.uuid = uuid; } + + public String getUUID() { return this.uuid; } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostCreateNewVnfRestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostCreateNewVnfRestObject.java new file mode 100644 index 000000000..86cbab8a6 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostCreateNewVnfRestObject.java @@ -0,0 +1,10 @@ +package org.openecomp.vid.scheduler.RestObjects; + +public class PostCreateNewVnfRestObject extends RestObject { + + public String uuid; + + public void setUUID(String uuid) { this.uuid = uuid; } + + public String getUUID() { return this.uuid; } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostSubmitVnfChangeRestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostSubmitVnfChangeRestObject.java new file mode 100644 index 000000000..6fb56f67d --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/PostSubmitVnfChangeRestObject.java @@ -0,0 +1,10 @@ +package org.openecomp.vid.scheduler.RestObjects; + +public class PostSubmitVnfChangeRestObject extends RestObject { + + public String uuid; + + public void setUUID(String uuid) { this.uuid = uuid; } + + public String getUUID() { return this.uuid; } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/RestObject.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/RestObject.java new file mode 100644 index 000000000..2d0eec74d --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/RestObjects/RestObject.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.scheduler.RestObjects; + + +public class RestObject { + + private T t; + + private int statusCode= 0; + + public void set(T t) { this.t = t; } + + public T get() { return t; } + + public void setStatusCode(int v) { this.statusCode = v; } + + public int getStatusCode() { return this.statusCode; } + +} + diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerProperties.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerProperties.java new file mode 100644 index 000000000..15855b7be --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerProperties.java @@ -0,0 +1,24 @@ +package org.openecomp.vid.scheduler; + +import org.openecomp.portalsdk.core.util.SystemProperties; + + +public class SchedulerProperties extends SystemProperties { + + public static final String SCHEDULER_USER_NAME_VAL = "scheduler.user.name"; + + public static final String SCHEDULER_PASSWORD_VAL = "scheduler.password"; + + public static final String SCHEDULER_SERVER_URL_VAL = "scheduler.server.url"; + + public static final String SCHEDULER_CREATE_NEW_VNF_CHANGE_INSTANCE_VAL = "scheduler.create.new.vnf.change.instance"; + + public static final String SCHEDULER_GET_TIME_SLOTS = "scheduler.get.time.slots"; + + public static final String SCHEDULER_SUBMIT_NEW_VNF_CHANGE = "scheduler.submit.new.vnf.change"; + + public static final String SCHEDULER_GET_SCHEDULES = "scheduler.get.schedules"; + + public static final String GET_VERSION_BY_INVARIANT_ID = "aai_get_version_by_invariant_id"; + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrapper.java new file mode 100644 index 000000000..5f148c06b --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrapper.java @@ -0,0 +1,71 @@ +package org.openecomp.vid.scheduler; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * This wrapper encapsulates the Scheduler response + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "status", + "entity", + "uuid" +}) + +public class SchedulerResponseWrapper { + + @JsonProperty("status") + private int status; + + @JsonProperty("entity") + private String entity; + + @JsonProperty("uuid") + private String uuid; + + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + @JsonProperty("status") + public int getStatus() { + return status; + } + + @JsonProperty("uuid") + public String getUuid() { + return uuid; + } + + @JsonProperty("status") + public void setStatus(int v) { + this.status = v; + } + + @JsonProperty("entity") + public void setEntity(String v) { + this.entity = v; + } + + @JsonProperty("uuid") + public void setUuid(String v) { + this.uuid = v; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String getResponse () { + + StringBuilder b = new StringBuilder ("{ \"status\": "); + b.append(getStatus()).append(", \"entity\": \" " ).append(this.getEntity()).append("\" ,\"uuid\": \"" ).append(this.getUuid()).append("\"}"); + return (b.toString()); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/GetTimeSlotsWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/GetTimeSlotsWrapper.java new file mode 100644 index 000000000..e5001d41f --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/GetTimeSlotsWrapper.java @@ -0,0 +1,5 @@ +package org.openecomp.vid.scheduler.SchedulerResponseWrappers; + +public class GetTimeSlotsWrapper extends SchedulerResponseWrapper { + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostCreateNewVnfWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostCreateNewVnfWrapper.java new file mode 100644 index 000000000..f1baeaf6e --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostCreateNewVnfWrapper.java @@ -0,0 +1,39 @@ +package org.openecomp.vid.scheduler.SchedulerResponseWrappers; + +import org.apache.commons.lang.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "uuid" +}) +public class PostCreateNewVnfWrapper extends SchedulerResponseWrapper { + + @JsonProperty("uuid") + private String uuid; + + @JsonProperty("uuid") + public String getUuid() { + return uuid; + } + + @JsonProperty("uuid") + public void setUuid(String v) { + this.uuid = v; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String getResponse () { + + StringBuilder b = new StringBuilder ("{ \"status\": "); + b.append(getStatus()).append(", \"entity\": \" " ).append(this.getEntity()).append("\" ,\"uuid\": \"" ).append(this.getUuid()).append("\"}"); + return (b.toString()); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostSubmitVnfChangeTimeSlotsWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostSubmitVnfChangeTimeSlotsWrapper.java new file mode 100644 index 000000000..86e4c0a74 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/PostSubmitVnfChangeTimeSlotsWrapper.java @@ -0,0 +1,38 @@ +package org.openecomp.vid.scheduler.SchedulerResponseWrappers; + +import org.apache.commons.lang.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "uuid" +}) +public class PostSubmitVnfChangeTimeSlotsWrapper extends SchedulerResponseWrapper { + @JsonProperty("uuid") + private String uuid; + + @JsonProperty("uuid") + public String getUuid() { + return uuid; + } + + @JsonProperty("uuid") + public void setUuid(String v) { + this.uuid = v; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String getResponse () { + + StringBuilder b = new StringBuilder ("{ \"status\": "); + b.append(getStatus()).append(", \"entity\": \" " ).append(this.getEntity()).append("\" ,\"uuid\": \"" ).append(this.getUuid()).append("\"}"); + return (b.toString()); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/SchedulerResponseWrapper.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/SchedulerResponseWrapper.java new file mode 100644 index 000000000..081ed3dc4 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerResponseWrappers/SchedulerResponseWrapper.java @@ -0,0 +1,57 @@ +package org.openecomp.vid.scheduler.SchedulerResponseWrappers; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * This wrapper encapsulates the Scheduler response + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "status", + "entity" +}) + +public class SchedulerResponseWrapper { + + @JsonProperty("status") + private int status; + + @JsonProperty("entity") + private String entity; + + @JsonProperty("entity") + public String getEntity() { + return entity; + } + + @JsonProperty("status") + public int getStatus() { + return status; + } + + @JsonProperty("status") + public void setStatus(int v) { + this.status = v; + } + + @JsonProperty("entity") + public void setEntity(String v) { + this.entity = v; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String getResponse () { + + StringBuilder b = new StringBuilder ("{ \"status\": "); + + b.append(getStatus()).append(", \"entity\": " ).append(this.getEntity()).append("}"); + return (b.toString()); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInt.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInt.java new file mode 100644 index 000000000..32b3a9c8c --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInt.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.scheduler; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; + +public class SchedulerRestInt { + + /** The logger. */ + EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerRestInterface.class); + + /** The Constant dateFormat. */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + /** The request date format. */ + public DateFormat requestDateFormat = new SimpleDateFormat("EEE, dd MMM YYYY HH:mm:ss z"); + + public SchedulerRestInt() { + requestDateFormat.setTimeZone(java.util.TimeZone.getTimeZone("GMT")); + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterface.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterface.java new file mode 100644 index 000000000..5f529f390 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterface.java @@ -0,0 +1,208 @@ +package org.openecomp.vid.scheduler; + +import java.util.Collections; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.Response; + +import org.apache.commons.codec.binary.Base64; +import org.eclipse.jetty.util.security.Password; +import org.json.simple.JSONObject; +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.client.HttpBasicClient; +import org.openecomp.vid.client.HttpsBasicClient; +import org.openecomp.vid.scheduler.SchedulerProperties; +import org.openecomp.vid.scheduler.RestObjects.RestObject; +import org.springframework.stereotype.Service; + +@Service +public class SchedulerRestInterface implements SchedulerRestInterfaceIfc { + + private static Client client = null; + + private MultivaluedHashMap commonHeaders; + + /** The logger. */ + static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerRestInterface.class); + + public SchedulerRestInterface() { + super(); + } + + public void initRestClient() + { + System.out.println( "\t <== Starting to initialize rest client "); + + final String username; + final String password; + + /*Setting user name based on properties*/ + String retrievedUsername = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_USER_NAME_VAL); + if(retrievedUsername.isEmpty()) { + username = ""; + } else { + username = retrievedUsername; + } + + /*Setting password based on properties*/ + String retrievedPassword = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_PASSWORD_VAL); + if(retrievedPassword.isEmpty()) { + password = ""; + } else { + if (retrievedPassword.contains("OBF:")) { + password = Password.deobfuscate(retrievedPassword); + } else { + password = retrievedPassword; + } + } + + String authString = username + ":" + password; + + byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); + String authStringEnc = new String(authEncBytes); + + commonHeaders = new MultivaluedHashMap (); + commonHeaders.put("Authorization", Collections.singletonList((Object) ("Basic " + authStringEnc))); + + try { + if ( !username.isEmpty() ) { + + client = HttpsBasicClient.getClient(); + } + else { + + client = HttpBasicClient.getClient(); + } + } catch (Exception e) { + System.out.println( " <== Unable to initialize rest client "); + } + + System.out.println( "\t<== Client Initialized \n"); + } + + @SuppressWarnings("unchecked") + public void Get (T t, String sourceId, String path, org.openecomp.vid.scheduler.RestObject restObject ) throws Exception { + + String methodName = "Get"; + String url = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SERVER_URL_VAL) + path; + + + System.out.println( "<== URL FOR GET : " + url + "\n"); + + initRestClient(); + + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .get(); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if (status == 200) { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + + } else { + throw new Exception(methodName + " with status="+ status + ", url= " + url ); + } + + return; + } + + @SuppressWarnings("unchecked") + public void Post(T t, JSONObject requestDetails, String path, RestObject restObject) throws Exception { + + String methodName = "Post"; + String url = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SERVER_URL_VAL) + path; + + System.out.println( "<== URL FOR POST : " + url + "\n"); + + try { + + initRestClient(); + + // Change the content length + final Response cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + .post(Entity.entity(requestDetails, MediaType.APPLICATION_JSON)); + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + + System.out.println("<== " + methodName + " : No response entity, this is probably ok, e=" + e.getMessage()); + } + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + if ( status >= 200 && status <= 299 ) { + + System.out.println( "<== " + methodName + " : REST api POST was successful!" + "\n"); + + } else { + System.out.println( "<== " + methodName + " : FAILED with http status : "+status+", url = " + url + "\n"); + } + + } catch (Exception e) + { + System.out.println( "<== " + methodName + " : with url="+url+ ", Exception: " + e.toString() + "\n"); + throw e; + } + } + + @Override + public void logRequest(JSONObject requestDetails) {} + + @SuppressWarnings("unchecked") + public void Delete(T t, JSONObject requestDetails, String sourceID, String path, RestObject restObject) { + + String url=""; + Response cres = null; + + try { + initRestClient(); + + url = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_SERVER_URL_VAL) + path; + + cres = client.target(url) + .request() + .accept("application/json") + .headers(commonHeaders) + //.entity(r) + .build("DELETE", Entity.entity(requestDetails, MediaType.APPLICATION_JSON)).invoke(); + // .method("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON)); + //.delete(Entity.entity(r, MediaType.APPLICATION_JSON)); + + int status = cres.getStatus(); + restObject.setStatusCode (status); + + try { + t = (T) cres.readEntity(t.getClass()); + restObject.set(t); + } + catch ( Exception e ) { + } + + } + catch (Exception e) + { + throw e; + } + } + + public T getInstance(Class clazz) throws IllegalAccessException, InstantiationException + { + return clazz.newInstance(); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceFactory.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceFactory.java new file mode 100644 index 000000000..bf7bd8891 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceFactory.java @@ -0,0 +1,15 @@ + +package org.openecomp.vid.scheduler; + +public class SchedulerRestInterfaceFactory { + + + public static SchedulerRestInterfaceIfc getInstance () { + SchedulerRestInterfaceIfc obj = null; + + obj = new SchedulerRestInterface(); + + return ( obj ); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceIfc.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceIfc.java new file mode 100644 index 000000000..839ab348d --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerRestInterfaceIfc.java @@ -0,0 +1,21 @@ + +package org.openecomp.vid.scheduler; + +import org.json.simple.JSONObject; +import org.openecomp.vid.scheduler.RestObjects.RestObject; +import org.springframework.stereotype.Service; + +@Service +public interface SchedulerRestInterfaceIfc { + + public void initRestClient(); + + public void Get (T t, String sourceId, String path, org.openecomp.vid.scheduler.RestObject restObject ) throws Exception; + + public void Delete(T t, JSONObject requestDetails, String sourceID, String path, RestObject restObject) + throws Exception; + + public void Post(T t, JSONObject r, String path, RestObject restObject) throws Exception; + + public void logRequest(JSONObject requestDetails); +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerUtil.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerUtil.java new file mode 100644 index 000000000..f82f474f6 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/SchedulerUtil.java @@ -0,0 +1,100 @@ +package org.openecomp.vid.scheduler; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.GetTimeSlotsWrapper; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.PostCreateNewVnfWrapper; +import org.openecomp.vid.scheduler.SchedulerResponseWrappers.PostSubmitVnfChangeTimeSlotsWrapper; +import org.openecomp.vid.scheduler.SchedulerUtil; +import org.openecomp.vid.scheduler.RestObjects.GetTimeSlotsRestObject; +import org.openecomp.vid.scheduler.RestObjects.PostCreateNewVnfRestObject; +import org.openecomp.vid.scheduler.RestObjects.PostSubmitVnfChangeRestObject; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SchedulerUtil { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SchedulerUtil.class); + + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + public static GetTimeSlotsWrapper getTimeSlotsWrapResponse (GetTimeSlotsRestObject rs) { + + String resp_str = ""; + int status = 0; + + if ( rs != null ) { + resp_str = rs.get(); + status = rs.getStatusCode(); + } + + GetTimeSlotsWrapper w = new GetTimeSlotsWrapper(); + + w.setEntity(resp_str); + w.setStatus (status); + + return (w); + } + + public static PostSubmitVnfChangeTimeSlotsWrapper postSubmitNewVnfWrapResponse (PostSubmitVnfChangeRestObject rs) { + + String resp_str = ""; + int status = 0; + String uuid = ""; + + if ( rs != null ) { + resp_str = rs.get(); + status = rs.getStatusCode(); + uuid = rs.getUUID(); + } + + PostSubmitVnfChangeTimeSlotsWrapper w = new PostSubmitVnfChangeTimeSlotsWrapper(); + + w.setEntity(resp_str); + w.setStatus (status); + w.setUuid(uuid); + + return (w); + } + + public static PostCreateNewVnfWrapper postCreateNewVnfWrapResponse (PostCreateNewVnfRestObject rs) { + + String resp_str = ""; + int status = 0; + String uuid = ""; + + if ( rs != null ) { + resp_str = rs.get(); + status = rs.getStatusCode(); + uuid = rs.getUUID(); + } + + PostCreateNewVnfWrapper w = new PostCreateNewVnfWrapper(); + + w.setEntity(resp_str); + w.setStatus (status); + w.setUuid(uuid); + + return (w); + } + + public static String convertPojoToString ( T t ) throws com.fasterxml.jackson.core.JsonProcessingException { + + String methodName = "convertPojoToString"; + ObjectMapper mapper = new ObjectMapper(); + String r_json_str = ""; + if ( t != null ) { + try { + r_json_str = mapper.writeValueAsString(t); + } + catch ( com.fasterxml.jackson.core.JsonProcessingException j ) { + logger.debug(EELFLoggerDelegate.debugLogger,dateFormat.format(new Date()) + "<== " + methodName + " Unable to parse object as json"); + } + } + return (r_json_str); + } + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/scheduler/rest/RequestDetails.java b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/rest/RequestDetails.java new file mode 100644 index 000000000..746fd9b24 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/scheduler/rest/RequestDetails.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.vid.scheduler.rest; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; +//import javax.annotation.Generated; + +import org.openecomp.vid.domain.mso.CloudConfiguration; +import org.openecomp.vid.domain.mso.ModelInfo; +import org.openecomp.vid.domain.mso.RequestInfo; +import org.openecomp.vid.domain.mso.RequestParameters; +import org.openecomp.vid.domain.mso.SubscriberInfo; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; + +/* + * "domain" : "ChangeManagement", + "scheduleId" : "3569b875-d40e-4adb-a288-a74f4b59ec1c", + "scheduleName" : "VnfUpgrade/DWF", + "userId" : "jf9860@att.com", + "domainData" : { + "WorkflowName" : "HEAT Stack Software Update for vNFs" + }, + "status" : "PendingOptimization", + "schedulingInfo" : { + "scheduleId" : "ChangeManagement.3569b875-d40e-4adb-a288-a74f4b59ec1c", + "normalDurationInSecs" : 60, + "AdditionalDurationInSecs" : 0, + "concurrencyLimit" : 10, + "policyId" : ["SNIRO.TimeLimitAndVerticalTopology"], + "groups" : [{ + "groupId" : " group1", + "node" : ["satmo415vbc", "satmo455vbc"], + "changeWindows" : [{ + "startTime" : "2017-02-15T01:00:00Z", + "finishTime" : "2017-02-15T02:00:00Z" + } + ] + }, { + "groupId" : " group2", + "node" : ["satmo555vbc"], + "changeWindows" : [{ + "startTime" : "2017-02-15T01:00:00Z", + "finishTime" : "2017-02-15T02:00:00Z" + }, { + "startTime" : "2017-02-15T05:00:00Z", + "finishTime" : "2017-02-15T05:30:00Z" + } + ] + } + ] +*/ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "domain", + "scheduleId", + "scheduleName", + "userId", + "domainData", + "status", + "schcedulingInfo" +}) +public class RequestDetails { + + @JsonProperty("domain") + private String domain; + + + + @JsonProperty("domain") + public String getDomain() { + return domain; + } + + @JsonProperty("domain") + public void setDomain(String domain) { + this.domain = domain; + } +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/AaiService.java b/vid-app-common/src/main/java/org/openecomp/vid/services/AaiService.java index 274419fb8..d3bacadec 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/services/AaiService.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/AaiService.java @@ -5,6 +5,7 @@ import org.openecomp.vid.aai.SubscriberFilteredResults; import org.openecomp.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.openecomp.vid.roles.RoleValidator; +import javax.ws.rs.core.Response; import java.util.List; /** @@ -21,5 +22,13 @@ public interface AaiService { AaiResponse getAaiZones(); + AaiResponse getAicZoneForPnf(String globalCustomerId , String serviceType , String serviceId); + + Response getVNFData(String globalSubscriberId, String serviceType); + AaiResponse getTenants(String globalCustomerId, String serviceType, RoleValidator roleValidator); + + AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId); + + Response getVersionByInvariantId(List modelInvariantId); } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/AaiServiceImpl.java b/vid-app-common/src/main/java/org/openecomp/vid/services/AaiServiceImpl.java index 38b670fe5..cb0962869 100644 --- a/vid-app-common/src/main/java/org/openecomp/vid/services/AaiServiceImpl.java +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/AaiServiceImpl.java @@ -1,12 +1,17 @@ package org.openecomp.vid.services; import org.ecomp.aai.model.AaiAICZones.AicZones; +import org.openecomp.portalsdk.core.util.SystemProperties; import org.openecomp.vid.aai.*; import org.openecomp.vid.aai.model.AaiGetServicesRequestModel.*; import org.openecomp.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.openecomp.vid.model.*; import org.openecomp.vid.roles.RoleValidator; +import org.openecomp.vid.scheduler.SchedulerProperties; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; + +import javax.ws.rs.core.Response; import java.util.List; @@ -37,12 +42,22 @@ public class AaiServiceImpl implements AaiService { String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { String serviceType = serviceSubscription.serviceType; - serviceSubscription.isPermitted = roleProvider.isServicePermitted(subscriberGlobalId,serviceType);; + serviceSubscription.isPermitted = roleProvider.isServicePermitted(subscriberGlobalId,serviceType); } return subscriberResponse; } + @Override + public Response getVersionByInvariantId(List modelInvariantId) { + try { + return aaiClient.getVersionByInvariantId(modelInvariantId); + }catch (Exception e){ + e.printStackTrace(); + } + return null; + } + @Override public AaiResponse getServices(RoleValidator roleValidator) { AaiResponse subscriberResponse = aaiClient.getServices(); @@ -62,9 +77,25 @@ public class AaiServiceImpl implements AaiService { return aaiGetTenantsResponse; } - @Override + @Override + public AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId) { + return aaiClient.getVNFData(globalSubscriberId,serviceType,serviceInstanceId); + } + + @Override + public Response getVNFData(String globalSubscriberId, String serviceType) { + return aaiClient.getVNFData(globalSubscriberId,serviceType); + } + + @Override public AaiResponse getAaiZones() { AaiResponse response = aaiClient.getAllAicZones(); return response; } + + @Override + public AaiResponse getAicZoneForPnf(String globalCustomerId , String serviceType , String serviceId) { + AaiResponse response = aaiClient.getAicZoneForPnf(globalCustomerId , serviceType , serviceId); + return response; + } } diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementService.java b/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementService.java new file mode 100644 index 000000000..3ac528282 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementService.java @@ -0,0 +1,14 @@ +package org.openecomp.vid.services; + +import org.openecomp.vid.changeManagement.ChangeManagementRequest; +import org.json.simple.JSONArray; +import org.openecomp.vid.mso.rest.Request; +import org.springframework.http.ResponseEntity; + +import java.util.Collection; + +public interface ChangeManagementService { + Collection getMSOChangeManagements(); + ResponseEntity doChangeManagement(ChangeManagementRequest request, String vnfName); + JSONArray getSchedulerChangeManagements(); +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementServiceImpl.java b/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementServiceImpl.java new file mode 100644 index 000000000..7e69d8fec --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/ChangeManagementServiceImpl.java @@ -0,0 +1,109 @@ +package org.openecomp.vid.services; + +import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.openecomp.vid.changeManagement.ChangeManagementRequest; +import org.openecomp.vid.changeManagement.RequestDetails; +import org.openecomp.vid.mso.MsoBusinessLogic; +import org.openecomp.vid.mso.MsoResponseWrapper; +import org.openecomp.vid.controller.MsoController; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.scheduler.*; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.openecomp.vid.mso.rest.Request; +import org.springframework.stereotype.Service; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; + +import java.util.Date; +import java.util.List; +import java.util.Collection; + + +@Service +public class ChangeManagementServiceImpl implements ChangeManagementService { + @Override + public Collection getMSOChangeManagements() { + Collection result = null; + MsoBusinessLogic msoBusinessLogic = new MsoBusinessLogic(); + try { + result = msoBusinessLogic.getOrchestrationRequestsForDashboard(); + } catch (Exception e) { + e.printStackTrace(); + } + + return result; + } + + private RequestDetails findRequestByVnfName(List requests, String vnfName){ + + if (requests == null) + return null; + + for(RequestDetails requestDetails: requests){ + if(requestDetails.getVnfName().equals(vnfName)){ + return requestDetails; + } + } + + return null; + } + + @Override + public ResponseEntity doChangeManagement(ChangeManagementRequest request, String vnfName) { + if (request == null) + return null; + ResponseEntity response = null; + RequestDetails currentRequestDetails = findRequestByVnfName(request.getRequestDetails(), vnfName); + MsoResponseWrapper msoResponseWrapperObject = null; + if(currentRequestDetails != null){ + MsoBusinessLogic msoBusinessLogicObject = new MsoBusinessLogic(); + String serviceInstanceId = currentRequestDetails.getRelatedInstList().get(0).getRelatedInstance().getInstanceId(); + String vnfInstanceId = currentRequestDetails.getVnfInstanceId(); + try { + if (request.getRequestType().equalsIgnoreCase("update")) { + + msoResponseWrapperObject = msoBusinessLogicObject.updateVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId); + } + else if (request.getRequestType().equalsIgnoreCase("replace")) + { + msoResponseWrapperObject = msoBusinessLogicObject.replaceVnf(currentRequestDetails, serviceInstanceId, vnfInstanceId); +// throw new NotImplementedException(); + } + response = new ResponseEntity(msoResponseWrapperObject.getResponse(), HttpStatus.OK); + return response; + } catch (Exception e) { + e.printStackTrace(); + } + + } + + // AH:TODO: return ChangeManagementResponse + return null; + } + + @Override + public JSONArray getSchedulerChangeManagements() { + JSONArray result = null; + try { + String path = SystemProperties.getProperty(SchedulerProperties.SCHEDULER_GET_SCHEDULES); + org.openecomp.vid.scheduler.RestObject restObject = new org.openecomp.vid.scheduler.RestObject<>(); + SchedulerRestInterfaceIfc restClient = SchedulerRestInterfaceFactory.getInstance(); + + String str = new String(); + restObject.set(str); + restClient.Get(str, "", path, restObject); + String restCallResult = restObject.get(); + JSONParser parser = new JSONParser(); + Object parserResult = parser.parse(restCallResult); + result = (JSONArray) parserResult; + } catch (Exception e) { + e.printStackTrace(); + } + + return result; + } + + +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowService.java b/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowService.java new file mode 100644 index 000000000..7f43433de --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowService.java @@ -0,0 +1,9 @@ +package org.openecomp.vid.services; + +import org.openecomp.vid.model.Workflow; +import java.util.Collection; + +public interface WorkflowService { + Collection getWorkflowsForVNFs(Collection vnfNames); + Collection getAllWorkflows(); +} diff --git a/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowServiceImpl.java b/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowServiceImpl.java new file mode 100644 index 000000000..deb506069 --- /dev/null +++ b/vid-app-common/src/main/java/org/openecomp/vid/services/WorkflowServiceImpl.java @@ -0,0 +1,40 @@ +package org.openecomp.vid.services; + +import org.openecomp.vid.model.Workflow; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Collectors; + +@Service +public class WorkflowServiceImpl implements WorkflowService { + //TODO: Add the list of workflows hard coded or from DB. + private ArrayList workflows = new ArrayList<>(Arrays.asList( + new Workflow(0, "Upgrade", new ArrayList<>(Arrays.asList("VNF1", "VNF2", "VNF3", "VNF4"))), + new Workflow(1, "Clean", new ArrayList<>(Arrays.asList("VNF1", "VNF2", "VNF3"))), + new Workflow(2, "Reinstall", new ArrayList<>(Arrays.asList("VNF1", "VNF2", "VNF4"))), + new Workflow(3, "Dump", new ArrayList<>(Arrays.asList("VNF1", "VNF3", "VNF4"))), + new Workflow(4, "Flush", new ArrayList<>(Arrays.asList("VNF2", "VNF3", "VNF4"))) + )); + + @Override + public Collection getWorkflowsForVNFs(Collection vnfNames) { + Collection result = workflows.stream() + .filter(workflow -> workflow.getVnfNames().containsAll(vnfNames)) + .map(workflow -> workflow.getWorkflowName()) + .distinct() + .collect(Collectors.toList()); + + return result; + } + + @Override + public Collection getAllWorkflows() { + return workflows.stream() + .map(workflow -> workflow.getWorkflowName()) + .distinct() + .collect(Collectors.toList()); + } +} diff --git a/vid-app-common/src/main/resources/json/mso/modelInfo b/vid-app-common/src/main/resources/json/mso/modelInfo index 2504d517b..dcb31128d 100755 --- a/vid-app-common/src/main/resources/json/mso/modelInfo +++ b/vid-app-common/src/main/resources/json/mso/modelInfo @@ -7,11 +7,19 @@ "description": "reference to the customized set of parameters associated with a model in a given service context", "type": "string" }, + "modelCustomizationId": { + "description": "reference to the customized set of parameters associated with a model in a given service context", + "type": "string" + }, "modelInvariantId": { "description": "Invariant UUID for the model name, irrespective of the version, as defined in SDC--authoritative", "type": "string", "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "modelVersionId": { + "description": "Version id for version", + "type": "string" + }, "modelName": { "description": "name of the model as defined in SDC--not authoritative", "type": "string" @@ -29,12 +37,13 @@ "service", "vfModule", "vnf", - "volumeGroup" + "volumeGroup", + "configuration" ] }, "modelVersion": { "description": "the version of the model as defined in SDC--not authoritative", - "type": "number" + "type": "string" } }, "required": ["modelType"] diff --git a/vid-app-common/src/main/resources/json/mso/request b/vid-app-common/src/main/resources/json/mso/request index 3aaadbfbc..95720bf91 100755 --- a/vid-app-common/src/main/resources/json/mso/request +++ b/vid-app-common/src/main/resources/json/mso/request @@ -22,7 +22,9 @@ "service", "vfModule", "vnf", - "volumeGroup" + "volumeGroup", + "unknown", + "configuration" ] }, "requestStatus": {}, @@ -33,7 +35,11 @@ "createInstance", "deleteInstance", "replaceInstance", - "updateInstance" + "updateInstance", + "activateInstance", + "deactivateInstance", + "unknown", + "not provided" ] }, "startTime": { diff --git a/vid-app-common/src/main/resources/json/mso/requestInfo b/vid-app-common/src/main/resources/json/mso/requestInfo index 56db42fce..5fcf74c7c 100755 --- a/vid-app-common/src/main/resources/json/mso/requestInfo +++ b/vid-app-common/src/main/resources/json/mso/requestInfo @@ -37,6 +37,14 @@ "suppressRollback": { "description": "true or false boolean indicating whether rollbacks should be suppressed on failures", "type": "boolean" + }, + "responseValue": { + "description": "Is the user selected value based on the validResponses list provided to complete the manual task", + "type": "string" + }, + "requestorId": { + "description": "The id of the person who initiated the completion request", + "type": "string" } }, diff --git a/vid-app-common/src/main/resources/json/mso/requestStatus b/vid-app-common/src/main/resources/json/mso/requestStatus index 9eacb6bb1..11b285636 100755 --- a/vid-app-common/src/main/resources/json/mso/requestStatus +++ b/vid-app-common/src/main/resources/json/mso/requestStatus @@ -9,9 +9,13 @@ "requestState": { "description": "short description of the instantiation state", "enum": [ - "complete", - "failed", - "inProgress" + "COMPLETE", + "FAILED", + "IN_PROGRESS", + "PENDING", + "UNLOCKED", + "COMPLETED", + "" ], "type": "string" }, diff --git a/vid-app-common/src/main/resources/mso_complete_manual_task.json b/vid-app-common/src/main/resources/mso_complete_manual_task.json new file mode 100644 index 000000000..625c9d9d0 --- /dev/null +++ b/vid-app-common/src/main/resources/mso_complete_manual_task.json @@ -0,0 +1,5 @@ +{ + "taskRequestReference": { + "taskId": "daf4dd84-b77a-42da-a051-3239b7a9392c" + } +} diff --git a/vid-app-common/src/main/resources/mso_create_instance_response.json b/vid-app-common/src/main/resources/mso_create_instance_response.json new file mode 100644 index 000000000..19763bc9a --- /dev/null +++ b/vid-app-common/src/main/resources/mso_create_instance_response.json @@ -0,0 +1,6 @@ +{ + "requestReferences": { + "instanceId": "ba00de9b-3c3e-4b0a-a1ad-0c5489e711fb", + "requestId": "311cc766-b673-4a50-b9c5-471f68914586" + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json b/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json new file mode 100644 index 000000000..004280bce --- /dev/null +++ b/vid-app-common/src/main/resources/mso_get_manual_task_by_request_id.json @@ -0,0 +1,23 @@ +{ + "taskList":[ + { + "taskId":"daf4dd84-b77a-42da-a051-3239b7a9392c", + "type":"fallout", + "nfRole":"vSCP", + "subscriptionServiceType":"Mobility", + "originalRequestId":"za1234d1-5a33-55df-13ab-12abad84e335", + "originalRequestorId":"ss835w", + "errorSource":"A&AI", + "errorCode":"404", + "errorMessage":"Failed in A&AI 404", + "buildingBlockName":"DoCreateVfModule", + "buildingBlockStep":"invokeA&AI:getTenant", + "validResponses":[ + "rollback", + "abort", + "skip", + "retry" + ] + } + ] +} \ No newline at end of file diff --git a/vid-app-common/src/main/resources/mso_get_orchestration_requests.json b/vid-app-common/src/main/resources/mso_get_orchestration_requests.json new file mode 100644 index 000000000..430ebc498 --- /dev/null +++ b/vid-app-common/src/main/resources/mso_get_orchestration_requests.json @@ -0,0 +1,88 @@ +{ + "requestList":[ + { + "request":{ + "requestId":"25272f7e-74c6-4afc-966a-4587f2c30bae", + "startTime":"Mon, 31 Jul 2017 23:25:30 GMT", + "requestScope":"vnf", + "requestType":"updateInstance", + "requestDetails":null, + "instanceReferences":{ + "serviceInstanceId":null, + "serviceInstanceName":null, + "vnfInstanceId":null, + "vnfInstanceName":null, + "vfModuleInstanceId":null, + "vfModuleInstanceName":null, + "volumeGroupInstanceId":null, + "volumeGroupInstanceName":null, + "networkInstanceId":null, + "networkInstanceName":null, + "requestorId":"md5621" + }, + "requestStatus":{ + "requestState":"IN_PROGRESS", + "statusMessage":null, + "percentProgress":20, + "finishTime":null + } + } + }, + { + "request":{ + "requestId":"25272f7e-74c6-4afc-966a-4587f2c30bae", + "startTime":"Mon, 31 Jul 2017 23:25:30 GMT", + "requestScope":"service", + "requestType":"createInstance", + "requestDetails":null, + "instanceReferences":{ + "serviceInstanceId":null, + "serviceInstanceName":null, + "vnfInstanceId":null, + "vnfInstanceName":null, + "vfModuleInstanceId":null, + "vfModuleInstanceName":null, + "volumeGroupInstanceId":null, + "volumeGroupInstanceName":null, + "networkInstanceId":null, + "networkInstanceName":null, + "requestorId":"md5621" + }, + "requestStatus":{ + "requestState":"IN_PROGRESS", + "statusMessage":null, + "percentProgress":20, + "finishTime":null + } + } + }, + { + "request":{ + "requestId":"9d6819e1-76e6-4e28-ad08-367632f41c7e", + "startTime":"Fri, 20 May 2016 19:07:57 GMT", + "requestScope":"vnf", + "requestType":"replaceInstance", + "requestDetails":null, + "instanceReferences":{ + "serviceInstanceId":null, + "serviceInstanceName":null, + "vnfInstanceId":null, + "vnfInstanceName":null, + "vfModuleInstanceId":null, + "vfModuleInstanceName":null, + "volumeGroupInstanceId":null, + "volumeGroupInstanceName":null, + "networkInstanceId":null, + "networkInstanceName":null, + "requestorId":null + }, + "requestStatus":{ + "requestState":"FAILED", + "statusMessage":"Service request FAILED schema validation. No valid format for volume request is specified", + "percentProgress":100, + "finishTime":"Fri, 20 May 2016 19:07:57 GMT" + } + } + } + ] +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/css/bootstrap.min.css b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..ed3905e0e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.eot b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 000000000..b93a4953f Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.eot differ diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.svg b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 000000000..94fb5490a --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.ttf b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 000000000..1413fc609 Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.ttf differ diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 000000000..9e612858f Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff differ diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 000000000..64539b54c Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/vid-app-common/src/main/webapp/app/vid/external/bootstrap/js/bootstrap.min.js b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/js/bootstrap.min.js new file mode 100644 index 000000000..9bcd2fcca --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/external/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth

',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/external/lodash/lodash.min.js b/vid-app-common/src/main/webapp/app/vid/external/lodash/lodash.min.js new file mode 100644 index 000000000..ca447f4e8 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/external/lodash/lodash.min.js @@ -0,0 +1,136 @@ +/** + * @license + * Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE + */ +;(function(){function n(n,t){return n.set(t[0],t[1]),n}function t(n,t){return n.add(t),n}function r(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function e(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u"']/g,J=RegExp(G.source),Y=RegExp(H.source),Q=/<%-([\s\S]+?)%>/g,X=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,rn=/^\w*$/,en=/^\./,un=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,on=/[\\^$.*+?()[\]{}|]/g,fn=RegExp(on.source),cn=/^\s+|\s+$/g,an=/^\s+/,ln=/\s+$/,sn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,hn=/\{\n\/\* \[wrapped with (.+)\] \*/,pn=/,? & /,_n=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,vn=/\\(\\)?/g,gn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,dn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,bn=/^0b[01]+$/i,xn=/^\[object .+?Constructor\]$/,jn=/^0o[0-7]+$/i,wn=/^(?:0|[1-9]\d*)$/,mn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,An=/($^)/,kn=/['\n\r\u2028\u2029\\]/g,En="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",On="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+En,Sn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",In=RegExp("['\u2019]","g"),Rn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),zn=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+Sn+En,"g"),Wn=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)|\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)|\\d+",On].join("|"),"g"),Bn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),Ln=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Un="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Cn={}; +Cn["[object Float32Array]"]=Cn["[object Float64Array]"]=Cn["[object Int8Array]"]=Cn["[object Int16Array]"]=Cn["[object Int32Array]"]=Cn["[object Uint8Array]"]=Cn["[object Uint8ClampedArray]"]=Cn["[object Uint16Array]"]=Cn["[object Uint32Array]"]=true,Cn["[object Arguments]"]=Cn["[object Array]"]=Cn["[object ArrayBuffer]"]=Cn["[object Boolean]"]=Cn["[object DataView]"]=Cn["[object Date]"]=Cn["[object Error]"]=Cn["[object Function]"]=Cn["[object Map]"]=Cn["[object Number]"]=Cn["[object Object]"]=Cn["[object RegExp]"]=Cn["[object Set]"]=Cn["[object String]"]=Cn["[object WeakMap]"]=false; +var Dn={};Dn["[object Arguments]"]=Dn["[object Array]"]=Dn["[object ArrayBuffer]"]=Dn["[object DataView]"]=Dn["[object Boolean]"]=Dn["[object Date]"]=Dn["[object Float32Array]"]=Dn["[object Float64Array]"]=Dn["[object Int8Array]"]=Dn["[object Int16Array]"]=Dn["[object Int32Array]"]=Dn["[object Map]"]=Dn["[object Number]"]=Dn["[object Object]"]=Dn["[object RegExp]"]=Dn["[object Set]"]=Dn["[object String]"]=Dn["[object Symbol]"]=Dn["[object Uint8Array]"]=Dn["[object Uint8ClampedArray]"]=Dn["[object Uint16Array]"]=Dn["[object Uint32Array]"]=true, +Dn["[object Error]"]=Dn["[object Function]"]=Dn["[object WeakMap]"]=false;var Mn,Tn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$n=parseFloat,Fn=parseInt,Nn=typeof global=="object"&&global&&global.Object===Object&&global,Pn=typeof self=="object"&&self&&self.Object===Object&&self,Zn=Nn||Pn||Function("return this")(),qn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Vn=qn&&typeof module=="object"&&module&&!module.nodeType&&module,Kn=Vn&&Vn.exports===qn,Gn=Kn&&Nn.process; +n:{try{Mn=Gn&&Gn.binding&&Gn.binding("util");break n}catch(n){}Mn=void 0}var Hn=Mn&&Mn.isArrayBuffer,Jn=Mn&&Mn.isDate,Yn=Mn&&Mn.isMap,Qn=Mn&&Mn.isRegExp,Xn=Mn&&Mn.isSet,nt=Mn&&Mn.isTypedArray,tt=j("length"),rt=w({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I", +"\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C", +"\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i", +"\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S", +"\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe", +"\u0149":"'n","\u017f":"s"}),et=w({"&":"&","<":"<",">":">",'"':""","'":"'"}),ut=w({"&":"&","<":"<",">":">",""":'"',"'":"'"}),it=function w(En){function On(n){if(xu(n)&&!af(n)&&!(n instanceof Mn)){if(n instanceof zn)return n;if(ci.call(n,"__wrapped__"))return Pe(n)}return new zn(n)}function Sn(){}function zn(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=F}function Mn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1, +this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function dt(n,t,r,e,i,o){var f,c=1&t,a=2&t,l=4&t;if(r&&(f=i?r(n,e,i,o):r(n)),f!==F)return f;if(!bu(n))return n;if(e=af(n)){if(f=Ee(n),!c)return Mr(n,f)}else{var s=yo(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(sf(n))return Wr(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Oe(n),!c)return a?Fr(n,pt(f,n)):$r(n,ht(f,n))}else{if(!Dn[s])return i?n:{};f=Se(n,s,dt,c)}}if(o||(o=new Vn), +i=o.get(n))return i;o.set(n,f);var a=l?a?ye:de:a?Uu:Lu,p=e?F:a(n);return u(p||n,function(e,u){p&&(u=e,e=n[u]),at(f,u,dt(e,t,r,u,n,o))}),f}function yt(n){var t=Lu(n);return function(r){return bt(r,n,t)}}function bt(n,t,r){var e=r.length;if(null==n)return!e;for(n=ni(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===F&&!(u in n)||!i(o))return false}return true}function xt(n,t,r){if(typeof n!="function")throw new ei("Expected a function");return jo(function(){n.apply(F,r)},t)}function jt(n,t,r,e){var u=-1,i=c,o=true,f=n.length,s=[],h=t.length; +if(!f)return s;r&&(t=l(t,S(r))),e?(i=a,o=false):200<=t.length&&(i=R,o=false,t=new qn(t));n:for(;++ut}function Bt(n,t){return null!=n&&ci.call(n,t)}function Lt(n,t){return null!=n&&t in ni(n)}function Ut(n,t,r){for(var e=r?a:c,u=n[0].length,i=n.length,o=i,f=Hu(i),s=1/0,h=[];o--;){var p=n[o];o&&t&&(p=l(p,S(t))),s=Mi(p.length,s),f[o]=!r&&(t||120<=u&&120<=p.length)?new qn(o&&p):F}var p=n[0],_=-1,v=f[0];n:for(;++_t.length?n:It(n,vr(t,0,-1)),t=null==n?n:n[$e(Ge(t))],null==t?F:r(t,n,e)}function Mt(n){return xu(n)&&"[object Arguments]"==zt(n)}function Tt(n){return xu(n)&&"[object ArrayBuffer]"==zt(n)}function $t(n){return xu(n)&&"[object Date]"==zt(n)}function Ft(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!xu(n)&&!xu(t))t=n!==n&&t!==t;else n:{ +var i=af(n),o=af(t),f=i?"[object Array]":yo(n),c=o?"[object Array]":yo(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&sf(n)){if(!sf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Vn),t=i||gf(n)?_e(n,t,r,e,Ft,u):ve(n,t,f,r,e,Ft,u);else{if(!(1&r)&&(i=a&&ci.call(n,"__wrapped__"),f=o&&ci.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Vn),t=Ft(n,t,r,e,u);break n}if(c)t:if(u||(u=new Vn), +i=1&r,f=de(n),o=f.length,c=de(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ci.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++at?r:0,Re(t,r)?n[t]:F}function rr(n,t,r){var e=-1;return t=l(t.length?t:[Nu],S(je())),n=Yt(n,function(n){return{a:l(t,function(t){return t(n)}),b:++e,c:n}}),A(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e=f?c:c*("desc"==r[e]?-1:1); +break n}}e=n.b-t.b}return e})}function er(n,t){return ur(n,t,function(t,r){return Bu(n,r)})}function ur(n,t,r){for(var e=-1,u=t.length,i={};++et||9007199254740991t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Hu(u);++e=u){for(;e>>1,o=n[i];null!==o&&!Au(o)&&(r?o<=t:ot.length?n:It(n,vr(t,0,-1)), +null==n||delete n[$e(Ge(t))]}function Ar(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++ie)return e?wr(n[0]):[];for(var u=-1,i=Hu(e);++u=e?n:vr(n,t,r)}function Wr(n,t){if(t)return n.slice();var r=n.length,r=yi?yi(r):new n.constructor(r);return n.copy(r),r}function Br(n){var t=new n.constructor(n.byteLength);return new di(t).set(new di(n)),t}function Lr(n,t){return new n.constructor(t?Br(n.buffer):n.buffer,n.byteOffset,n.length)}function Ur(n,t){ +if(n!==t){var r=n!==F,e=null===n,u=n===n,i=Au(n),o=t!==F,f=null===t,c=t===t,a=Au(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&nu?F:i,u=1),t=ni(t);++eo&&f[0]!==a&&f[o-1]!==a?[]:C(f,a),o-=c.length,or?r?ar(t,n):t:(r=ar(t,Ri(n/T(t))),Bn.test(t)?zr($(r),0,n).join(""):r.slice(0,n))}function ue(n,t,e,u){function i(){for(var t=-1,c=arguments.length,a=-1,l=u.length,s=Hu(l+c),h=this&&this!==Zn&&this instanceof i?f:n;++at||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Cr(e,r,h[4]):r,i[4]=e?C(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Dr(e,r,h[6]):r,i[6]=e?C(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Mi(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1], +r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===F?c?0:n.length:Di(i[9]-a,0),!f&&24&t&&(t&=-25),De((h?lo:xo)(t&&1!=t?8==t||16==t?Jr(n,t,f):32!=t&&33!=t||u.length?Xr.apply(F,i):ue(n,t,r,e):Vr(n,t,r),i),n,t)}function se(n,t,r,e){return n===F||hu(n,ii[r])&&!ci.call(e,r)?t:n}function he(n,t,r,e,u,i){return bu(n)&&bu(t)&&(i.set(t,n),nr(n,t,F,he,i),i.delete(t)),n}function pe(n){return wu(n)?F:n}function _e(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new qn:F; +for(i.set(n,t),i.set(t,n);++cr&&(r=Di(e+r,0)),g(n,je(t,3),r)):-1}function qe(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==F&&(u=Ou(r),u=0>r?Di(e+u,0):Mi(u,e-1)), +g(n,je(t,3),u,true)}function Ve(n){return(null==n?0:n.length)?kt(n,1):[]}function Ke(n){return n&&n.length?n[0]:F}function Ge(n){var t=null==n?0:n.length;return t?n[t-1]:F}function He(n,t){return n&&n.length&&t&&t.length?or(n,t):n}function Je(n){return null==n?n:Ni.call(n)}function Ye(n){if(!n||!n.length)return[];var t=0;return n=f(n,function(n){if(_u(n))return t=Di(n.length,t),true}),E(t,function(t){return l(n,j(t))})}function Qe(n,t){if(!n||!n.length)return[];var e=Ye(n);return null==t?e:l(e,function(n){ +return r(t,F,n)})}function Xe(n){return n=On(n),n.__chain__=true,n}function nu(n,t){return t(n)}function tu(){return this}function ru(n,t){return(af(n)?u:oo)(n,je(t,3))}function eu(n,t){return(af(n)?i:fo)(n,je(t,3))}function uu(n,t){return(af(n)?l:Yt)(n,je(t,3))}function iu(n,t,r){return t=r?F:t,t=n&&null==t?n.length:t,le(n,128,F,F,F,F,t)}function ou(n,t){var r;if(typeof t!="function")throw new ei("Expected a function");return n=Ou(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=F), +r}}function fu(n,t,r){return t=r?F:t,n=le(n,8,F,F,F,F,F,t),n.placeholder=fu.placeholder,n}function cu(n,t,r){return t=r?F:t,n=le(n,16,F,F,F,F,F,t),n.placeholder=cu.placeholder,n}function au(n,t,r){function e(t){var r=c,e=a;return c=a=F,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===F||r>=t||0>r||g&&n>=l}function i(){var n=Jo();if(u(n))return o(n);var r,e=jo;r=n-_,n=t-(n-p),r=g?Mi(n,l-r):n,h=e(i,r)}function o(n){return h=F,d&&c?e(n):(c=a=F,s)}function f(){var n=Jo(),r=u(n);if(c=arguments, +a=this,p=n,r){if(h===F)return _=n=p,h=jo(i,t),v?e(n):s;if(g)return h=jo(i,t),e(p)}return h===F&&(h=jo(i,t)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ei("Expected a function");return t=Iu(t)||0,bu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Di(Iu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==F&&ho(h),_=0,c=p=a=h=F},f.flush=function(){return h===F?s:o(Jo())},f}function lu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e), +r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ei("Expected a function");return r.cache=new(lu.Cache||Pn),r}function su(n){if(typeof n!="function")throw new ei("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function hu(n,t){return n===t||n!==n&&t!==t}function pu(n){return null!=n&&yu(n.length)&&!gu(n); +}function _u(n){return xu(n)&&pu(n)}function vu(n){if(!xu(n))return false;var t=zt(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!wu(n)}function gu(n){return!!bu(n)&&(n=zt(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function du(n){return typeof n=="number"&&n==Ou(n)}function yu(n){return typeof n=="number"&&-1=n}function bu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t); +}function xu(n){return null!=n&&typeof n=="object"}function ju(n){return typeof n=="number"||xu(n)&&"[object Number]"==zt(n)}function wu(n){return!(!xu(n)||"[object Object]"!=zt(n))&&(n=bi(n),null===n||(n=ci.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&fi.call(n)==hi))}function mu(n){return typeof n=="string"||!af(n)&&xu(n)&&"[object String]"==zt(n)}function Au(n){return typeof n=="symbol"||xu(n)&&"[object Symbol]"==zt(n)}function ku(n){if(!n)return[];if(pu(n))return mu(n)?$(n):Mr(n); +if(Ai&&n[Ai]){n=n[Ai]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=yo(n),("[object Map]"==t?L:"[object Set]"==t?D:Du)(n)}function Eu(n){return n?(n=Iu(n),n===N||n===-N?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Ou(n){n=Eu(n);var t=n%1;return n===n?t?n-t:n:0}function Su(n){return n?gt(Ou(n),0,4294967295):0}function Iu(n){if(typeof n=="number")return n;if(Au(n))return P;if(bu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=bu(n)?n+"":n),typeof n!="string")return 0===n?n:+n; +n=n.replace(cn,"");var t=bn.test(n);return t||jn.test(n)?Fn(n.slice(2),t?2:8):yn.test(n)?P:+n}function Ru(n){return Tr(n,Uu(n))}function zu(n){return null==n?"":jr(n)}function Wu(n,t,r){return n=null==n?F:It(n,t),n===F?r:n}function Bu(n,t){return null!=n&&ke(n,t,Lt)}function Lu(n){return pu(n)?Gn(n):Ht(n)}function Uu(n){if(pu(n))n=Gn(n,true);else if(bu(n)){var t,r=Le(n),e=[];for(t in n)("constructor"!=t||!r&&ci.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in ni(n))t.push(r);n=t}return n}function Cu(n,t){ +if(null==n)return{};var r=l(ye(n),function(n){return[n]});return t=je(t),ur(n,r,function(n,r){return t(n,r[0])})}function Du(n){return null==n?[]:I(n,Lu(n))}function Mu(n){return Nf(zu(n).toLowerCase())}function Tu(n){return(n=zu(n))&&n.replace(mn,rt).replace(Rn,"")}function $u(n,t,r){return n=zu(n),t=r?F:t,t===F?Ln.test(n)?n.match(Wn)||[]:n.match(_n)||[]:n.match(t)||[]}function Fu(n){return function(){return n}}function Nu(n){return n}function Pu(n){return Gt(typeof n=="function"?n:dt(n,1))}function Zu(n,t,r){ +var e=Lu(t),i=St(t,e);null!=r||bu(t)&&(i.length||!e.length)||(r=t,t=n,n=this,i=St(t,Lu(t)));var o=!(bu(r)&&"chain"in r&&!r.chain),f=gu(n);return u(i,function(r){var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Mr(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,s([this.value()],arguments))})}),n}function qu(){}function Vu(n){return We(n)?j($e(n)):ir(n)}function Ku(){return[]}function Gu(){ +return false}En=null==En?Zn:it.defaults(Zn.Object(),En,it.pick(Zn,Un));var Hu=En.Array,Ju=En.Date,Yu=En.Error,Qu=En.Function,Xu=En.Math,ni=En.Object,ti=En.RegExp,ri=En.String,ei=En.TypeError,ui=Hu.prototype,ii=ni.prototype,oi=En["__core-js_shared__"],fi=Qu.prototype.toString,ci=ii.hasOwnProperty,ai=0,li=function(){var n=/[^.]+$/.exec(oi&&oi.keys&&oi.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),si=ii.toString,hi=fi.call(ni),pi=Zn._,_i=ti("^"+fi.call(ci).replace(on,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),vi=Kn?En.Buffer:F,gi=En.Symbol,di=En.Uint8Array,yi=vi?vi.f:F,bi=U(ni.getPrototypeOf,ni),xi=ni.create,ji=ii.propertyIsEnumerable,wi=ui.splice,mi=gi?gi.isConcatSpreadable:F,Ai=gi?gi.iterator:F,ki=gi?gi.toStringTag:F,Ei=function(){ +try{var n=Ae(ni,"defineProperty");return n({},"",{}),n}catch(n){}}(),Oi=En.clearTimeout!==Zn.clearTimeout&&En.clearTimeout,Si=Ju&&Ju.now!==Zn.Date.now&&Ju.now,Ii=En.setTimeout!==Zn.setTimeout&&En.setTimeout,Ri=Xu.ceil,zi=Xu.floor,Wi=ni.getOwnPropertySymbols,Bi=vi?vi.isBuffer:F,Li=En.isFinite,Ui=ui.join,Ci=U(ni.keys,ni),Di=Xu.max,Mi=Xu.min,Ti=Ju.now,$i=En.parseInt,Fi=Xu.random,Ni=ui.reverse,Pi=Ae(En,"DataView"),Zi=Ae(En,"Map"),qi=Ae(En,"Promise"),Vi=Ae(En,"Set"),Ki=Ae(En,"WeakMap"),Gi=Ae(ni,"create"),Hi=Ki&&new Ki,Ji={},Yi=Fe(Pi),Qi=Fe(Zi),Xi=Fe(qi),no=Fe(Vi),to=Fe(Ki),ro=gi?gi.prototype:F,eo=ro?ro.valueOf:F,uo=ro?ro.toString:F,io=function(){ +function n(){}return function(t){return bu(t)?xi?xi(t):(n.prototype=t,t=new n,n.prototype=F,t):{}}}();On.templateSettings={escape:Q,evaluate:X,interpolate:nn,variable:"",imports:{_:On}},On.prototype=Sn.prototype,On.prototype.constructor=On,zn.prototype=io(Sn.prototype),zn.prototype.constructor=zn,Mn.prototype=io(Sn.prototype),Mn.prototype.constructor=Mn,Tn.prototype.clear=function(){this.__data__=Gi?Gi(null):{},this.size=0},Tn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n], +this.size-=n?1:0,n},Tn.prototype.get=function(n){var t=this.__data__;return Gi?(n=t[n],"__lodash_hash_undefined__"===n?F:n):ci.call(t,n)?t[n]:F},Tn.prototype.has=function(n){var t=this.__data__;return Gi?t[n]!==F:ci.call(t,n)},Tn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=Gi&&t===F?"__lodash_hash_undefined__":t,this},Nn.prototype.clear=function(){this.__data__=[],this.size=0},Nn.prototype.delete=function(n){var t=this.__data__;return n=lt(t,n),!(0>n)&&(n==t.length-1?t.pop():wi.call(t,n,1), +--this.size,true)},Nn.prototype.get=function(n){var t=this.__data__;return n=lt(t,n),0>n?F:t[n][1]},Nn.prototype.has=function(n){return-1e?(++this.size,r.push([n,t])):r[e][1]=t,this},Pn.prototype.clear=function(){this.size=0,this.__data__={hash:new Tn,map:new(Zi||Nn),string:new Tn}},Pn.prototype.delete=function(n){return n=we(this,n).delete(n),this.size-=n?1:0,n},Pn.prototype.get=function(n){return we(this,n).get(n); +},Pn.prototype.has=function(n){return we(this,n).has(n)},Pn.prototype.set=function(n,t){var r=we(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},qn.prototype.add=qn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},qn.prototype.has=function(n){return this.__data__.has(n)},Vn.prototype.clear=function(){this.__data__=new Nn,this.size=0},Vn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Vn.prototype.get=function(n){ +return this.__data__.get(n)},Vn.prototype.has=function(n){return this.__data__.has(n)},Vn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Nn){var e=r.__data__;if(!Zi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Pn(e)}return r.set(n,t),this.size=r.size,this};var oo=Zr(Et),fo=Zr(Ot,true),co=qr(),ao=qr(true),lo=Hi?function(n,t){return Hi.set(n,t),n}:Nu,so=Ei?function(n,t){return Ei(n,"toString",{configurable:true,enumerable:false,value:Fu(t),writable:true})}:Nu,ho=Oi||function(n){ +return Zn.clearTimeout(n)},po=Vi&&1/D(new Vi([,-0]))[1]==N?function(n){return new Vi(n)}:qu,_o=Hi?function(n){return Hi.get(n)}:qu,vo=Wi?function(n){return null==n?[]:(n=ni(n),f(Wi(n),function(t){return ji.call(n,t)}))}:Ku,go=Wi?function(n){for(var t=[];n;)s(t,vo(n)),n=bi(n);return t}:Ku,yo=zt;(Pi&&"[object DataView]"!=yo(new Pi(new ArrayBuffer(1)))||Zi&&"[object Map]"!=yo(new Zi)||qi&&"[object Promise]"!=yo(qi.resolve())||Vi&&"[object Set]"!=yo(new Vi)||Ki&&"[object WeakMap]"!=yo(new Ki))&&(yo=function(n){ +var t=zt(n);if(n=(n="[object Object]"==t?n.constructor:F)?Fe(n):"")switch(n){case Yi:return"[object DataView]";case Qi:return"[object Map]";case Xi:return"[object Promise]";case no:return"[object Set]";case to:return"[object WeakMap]"}return t});var bo=oi?gu:Gu,xo=Me(lo),jo=Ii||function(n,t){return Zn.setTimeout(n,t)},wo=Me(so),mo=function(n){n=lu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return en.test(n)&&t.push(""),n.replace(un,function(n,r,e,u){ +t.push(e?u.replace(vn,"$1"):r||n)}),t}),Ao=lr(function(n,t){return _u(n)?jt(n,kt(t,1,_u,true)):[]}),ko=lr(function(n,t){var r=Ge(t);return _u(r)&&(r=F),_u(n)?jt(n,kt(t,1,_u,true),je(r,2)):[]}),Eo=lr(function(n,t){var r=Ge(t);return _u(r)&&(r=F),_u(n)?jt(n,kt(t,1,_u,true),F,r):[]}),Oo=lr(function(n){var t=l(n,Sr);return t.length&&t[0]===n[0]?Ut(t):[]}),So=lr(function(n){var t=Ge(n),r=l(n,Sr);return t===Ge(r)?t=F:r.pop(),r.length&&r[0]===n[0]?Ut(r,je(t,2)):[]}),Io=lr(function(n){var t=Ge(n),r=l(n,Sr);return(t=typeof t=="function"?t:F)&&r.pop(), +r.length&&r[0]===n[0]?Ut(r,F,t):[]}),Ro=lr(He),zo=ge(function(n,t){var r=null==n?0:n.length,e=vt(n,t);return fr(n,l(t,function(n){return Re(n,r)?+n:n}).sort(Ur)),e}),Wo=lr(function(n){return wr(kt(n,1,_u,true))}),Bo=lr(function(n){var t=Ge(n);return _u(t)&&(t=F),wr(kt(n,1,_u,true),je(t,2))}),Lo=lr(function(n){var t=Ge(n),t=typeof t=="function"?t:F;return wr(kt(n,1,_u,true),F,t)}),Uo=lr(function(n,t){return _u(n)?jt(n,t):[]}),Co=lr(function(n){return Er(f(n,_u))}),Do=lr(function(n){var t=Ge(n);return _u(t)&&(t=F), +Er(f(n,_u),je(t,2))}),Mo=lr(function(n){var t=Ge(n),t=typeof t=="function"?t:F;return Er(f(n,_u),F,t)}),To=lr(Ye),$o=lr(function(n){var t=n.length,t=1=t}),cf=Mt(function(){return arguments}())?Mt:function(n){return xu(n)&&ci.call(n,"callee")&&!ji.call(n,"callee")},af=Hu.isArray,lf=Hn?S(Hn):Tt,sf=Bi||Gu,hf=Jn?S(Jn):$t,pf=Yn?S(Yn):Nt,_f=Qn?S(Qn):qt,vf=Xn?S(Xn):Vt,gf=nt?S(nt):Kt,df=oe(Jt),yf=oe(function(n,t){return n<=t}),bf=Pr(function(n,t){ +if(Le(t)||pu(t))Tr(t,Lu(t),n);else for(var r in t)ci.call(t,r)&&at(n,r,t[r])}),xf=Pr(function(n,t){Tr(t,Uu(t),n)}),jf=Pr(function(n,t,r,e){Tr(t,Uu(t),n,e)}),wf=Pr(function(n,t,r,e){Tr(t,Lu(t),n,e)}),mf=ge(vt),Af=lr(function(n){return n.push(F,se),r(jf,F,n)}),kf=lr(function(n){return n.push(F,he),r(Rf,F,n)}),Ef=ne(function(n,t,r){n[t]=r},Fu(Nu)),Of=ne(function(n,t,r){ci.call(n,t)?n[t].push(r):n[t]=[r]},je),Sf=lr(Dt),If=Pr(function(n,t,r){nr(n,t,r)}),Rf=Pr(function(n,t,r,e){nr(n,t,r,e)}),zf=ge(function(n,t){ +var r={};if(null==n)return r;var e=false;t=l(t,function(t){return t=Rr(t,n),e||(e=1--n)return t.apply(this,arguments)}},On.ary=iu,On.assign=bf,On.assignIn=xf,On.assignInWith=jf,On.assignWith=wf,On.at=mf,On.before=ou,On.bind=Yo,On.bindAll=Zf,On.bindKey=Qo,On.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return af(n)?n:[n]}, +On.chain=Xe,On.chunk=function(n,t,r){if(t=(r?ze(n,t,r):t===F)?1:Di(Ou(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Hu(Ri(r/t));et?0:t,e)):[]},On.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===F?1:Ou(t),t=e-t,vr(n,0,0>t?0:t)):[]},On.dropRightWhile=function(n,t){return n&&n.length?Ar(n,je(t,3),true,true):[]},On.dropWhile=function(n,t){return n&&n.length?Ar(n,je(t,3),true):[]},On.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&ze(n,t,r)&&(r=0,e=u),u=n.length,r=Ou(r),0>r&&(r=-r>u?0:u+r),e=e===F||e>u?u:Ou(e),0>e&&(e+=u),e=r>e?0:Su(e);r>>0,r?(n=zu(n))&&(typeof t=="string"||null!=t&&!_f(t))&&(t=jr(t), +!t&&Bn.test(n))?zr($(n),0,r):n.split(t,r):[]},On.spread=function(n,t){if(typeof n!="function")throw new ei("Expected a function");return t=null==t?0:Di(Ou(t),0),lr(function(e){var u=e[t];return e=zr(e,0,t),u&&s(e,u),r(n,this,e)})},On.tail=function(n){var t=null==n?0:n.length;return t?vr(n,1,t):[]},On.take=function(n,t,r){return n&&n.length?(t=r||t===F?1:Ou(t),vr(n,0,0>t?0:t)):[]},On.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===F?1:Ou(t),t=e-t,vr(n,0>t?0:t,e)):[]},On.takeRightWhile=function(n,t){ +return n&&n.length?Ar(n,je(t,3),false,true):[]},On.takeWhile=function(n,t){return n&&n.length?Ar(n,je(t,3)):[]},On.tap=function(n,t){return t(n),n},On.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ei("Expected a function");return bu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),au(n,t,{leading:e,maxWait:t,trailing:u})},On.thru=nu,On.toArray=ku,On.toPairs=Bf,On.toPairsIn=Lf,On.toPath=function(n){return af(n)?l(n,$e):Au(n)?[n]:Mr(mo(zu(n)))},On.toPlainObject=Ru, +On.transform=function(n,t,r){var e=af(n),i=e||sf(n)||gf(n);if(t=je(t,4),null==r){var o=n&&n.constructor;r=i?e?new o:[]:bu(n)&&gu(o)?io(bi(n)):{}}return(i?u:Et)(n,function(n,e,u){return t(r,n,e,u)}),r},On.unary=function(n){return iu(n,1)},On.union=Wo,On.unionBy=Bo,On.unionWith=Lo,On.uniq=function(n){return n&&n.length?wr(n):[]},On.uniqBy=function(n,t){return n&&n.length?wr(n,je(t,2)):[]},On.uniqWith=function(n,t){return t=typeof t=="function"?t:F,n&&n.length?wr(n,F,t):[]},On.unset=function(n,t){return null==n||mr(n,t); +},On.unzip=Ye,On.unzipWith=Qe,On.update=function(n,t,r){return null==n?n:pr(n,t,Ir(r)(It(n,t)),void 0)},On.updateWith=function(n,t,r,e){return e=typeof e=="function"?e:F,null!=n&&(n=pr(n,t,Ir(r)(It(n,t)),e)),n},On.values=Du,On.valuesIn=function(n){return null==n?[]:I(n,Uu(n))},On.without=Uo,On.words=$u,On.wrap=function(n,t){return rf(Ir(t),n)},On.xor=Co,On.xorBy=Do,On.xorWith=Mo,On.zip=To,On.zipObject=function(n,t){return Or(n||[],t||[],at)},On.zipObjectDeep=function(n,t){return Or(n||[],t||[],pr); +},On.zipWith=$o,On.entries=Bf,On.entriesIn=Lf,On.extend=xf,On.extendWith=jf,Zu(On,On),On.add=nc,On.attempt=Pf,On.camelCase=Uf,On.capitalize=Mu,On.ceil=tc,On.clamp=function(n,t,r){return r===F&&(r=t,t=F),r!==F&&(r=Iu(r),r=r===r?r:0),t!==F&&(t=Iu(t),t=t===t?t:0),gt(Iu(n),t,r)},On.clone=function(n){return dt(n,4)},On.cloneDeep=function(n){return dt(n,5)},On.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:F,dt(n,5,t)},On.cloneWith=function(n,t){return t=typeof t=="function"?t:F,dt(n,4,t)}, +On.conformsTo=function(n,t){return null==t||bt(n,t,Lu(t))},On.deburr=Tu,On.defaultTo=function(n,t){return null==n||n!==n?t:n},On.divide=rc,On.endsWith=function(n,t,r){n=zu(n),t=jr(t);var e=n.length,e=r=r===F?e:gt(Ou(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},On.eq=hu,On.escape=function(n){return(n=zu(n))&&Y.test(n)?n.replace(H,et):n},On.escapeRegExp=function(n){return(n=zu(n))&&fn.test(n)?n.replace(on,"\\$&"):n},On.every=function(n,t,r){var e=af(n)?o:wt;return r&&ze(n,t,r)&&(t=F),e(n,je(t,3)); +},On.find=Po,On.findIndex=Ze,On.findKey=function(n,t){return v(n,je(t,3),Et)},On.findLast=Zo,On.findLastIndex=qe,On.findLastKey=function(n,t){return v(n,je(t,3),Ot)},On.floor=ec,On.forEach=ru,On.forEachRight=eu,On.forIn=function(n,t){return null==n?n:co(n,je(t,3),Uu)},On.forInRight=function(n,t){return null==n?n:ao(n,je(t,3),Uu)},On.forOwn=function(n,t){return n&&Et(n,je(t,3))},On.forOwnRight=function(n,t){return n&&Ot(n,je(t,3))},On.get=Wu,On.gt=of,On.gte=ff,On.has=function(n,t){return null!=n&&ke(n,t,Bt); +},On.hasIn=Bu,On.head=Ke,On.identity=Nu,On.includes=function(n,t,r,e){return n=pu(n)?n:Du(n),r=r&&!e?Ou(r):0,e=n.length,0>r&&(r=Di(e+r,0)),mu(n)?r<=e&&-1r&&(r=Di(e+r,0)),d(n,t,r)):-1},On.inRange=function(n,t,r){return t=Eu(t),r===F?(r=t,t=0):r=Eu(r),n=Iu(n),n>=Mi(t,r)&&n=n},On.isSet=vf,On.isString=mu,On.isSymbol=Au,On.isTypedArray=gf,On.isUndefined=function(n){return n===F},On.isWeakMap=function(n){return xu(n)&&"[object WeakMap]"==yo(n)},On.isWeakSet=function(n){return xu(n)&&"[object WeakSet]"==zt(n)},On.join=function(n,t){ +return null==n?"":Ui.call(n,t)},On.kebabCase=Cf,On.last=Ge,On.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==F&&(u=Ou(r),u=0>u?Di(e+u,0):Mi(u,e-1)),t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=g(n,b,u,true);return n},On.lowerCase=Df,On.lowerFirst=Mf,On.lt=df,On.lte=yf,On.max=function(n){return n&&n.length?mt(n,Nu,Wt):F},On.maxBy=function(n,t){return n&&n.length?mt(n,je(t,2),Wt):F},On.mean=function(n){return x(n,Nu)},On.meanBy=function(n,t){return x(n,je(t,2))},On.min=function(n){ +return n&&n.length?mt(n,Nu,Jt):F},On.minBy=function(n,t){return n&&n.length?mt(n,je(t,2),Jt):F},On.stubArray=Ku,On.stubFalse=Gu,On.stubObject=function(){return{}},On.stubString=function(){return""},On.stubTrue=function(){return true},On.multiply=uc,On.nth=function(n,t){return n&&n.length?tr(n,Ou(t)):F},On.noConflict=function(){return Zn._===this&&(Zn._=pi),this},On.noop=qu,On.now=Jo,On.pad=function(n,t,r){n=zu(n);var e=(t=Ou(t))?T(n):0;return!t||e>=t?n:(t=(t-e)/2,ee(zi(t),r)+n+ee(Ri(t),r))},On.padEnd=function(n,t,r){ +n=zu(n);var e=(t=Ou(t))?T(n):0;return t&&et){var e=n;n=t,t=e}return r||n%1||t%1?(r=Fi(),Mi(n+r*(t-n+$n("1e-"+((r+"").length-1))),t)):cr(n,t); +},On.reduce=function(n,t,r){var e=af(n)?h:m,u=3>arguments.length;return e(n,je(t,4),r,u,oo)},On.reduceRight=function(n,t,r){var e=af(n)?p:m,u=3>arguments.length;return e(n,je(t,4),r,u,fo)},On.repeat=function(n,t,r){return t=(r?ze(n,t,r):t===F)?1:Ou(t),ar(zu(n),t)},On.replace=function(){var n=arguments,t=zu(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},On.result=function(n,t,r){t=Rr(t,n);var e=-1,u=t.length;for(u||(u=1,n=F);++en||9007199254740991=i)return n;if(i=r-T(e),1>i)return e; +if(r=o?zr(o,0,i).join(""):n.slice(0,i),u===F)return r+e;if(o&&(i+=r.length-i),_f(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=ti(u.source,zu(dn.exec(u))+"g")),u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===F?i:c)}}else n.indexOf(jr(u),i)!=i&&(u=r.lastIndexOf(u),-1e.__dir__?"Right":"")}),e},Mn.prototype[n+"Right"]=function(t){ +return this.reverse()[n](t).reverse()}}),u(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Mn.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:je(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),u(["head","last"],function(n,t){var r="take"+(t?"Right":"");Mn.prototype[n]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Mn.prototype[n]=function(){return this.__filtered__?new Mn(this):this[r](1); +}}),Mn.prototype.compact=function(){return this.filter(Nu)},Mn.prototype.find=function(n){return this.filter(n).head()},Mn.prototype.findLast=function(n){return this.reverse().find(n)},Mn.prototype.invokeMap=lr(function(n,t){return typeof n=="function"?new Mn(this):this.map(function(r){return Dt(r,n,t)})}),Mn.prototype.reject=function(n){return this.filter(su(je(n)))},Mn.prototype.slice=function(n,t){n=Ou(n);var r=this;return r.__filtered__&&(0t)?new Mn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)), +t!==F&&(t=Ou(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Mn.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Mn.prototype.toArray=function(){return this.take(4294967295)},Et(Mn.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=On[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(On.prototype[t]=function(){function t(n){return n=u.apply(On,s([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Mn,a=f[0],l=c||af(o); +l&&r&&typeof a=="function"&&1!=a.length&&(c=l=false);var h=this.__chain__,p=!!this.__actions__.length,a=i&&!h,c=c&&!p;return!i&&l?(o=c?o:new Mn(this),o=n.apply(o,f),o.__actions__.push({func:nu,args:[t],thisArg:F}),new zn(o,h)):a&&c?n.apply(this,f):(o=this.thru(t),a?e?o.value()[0]:o.value():o)})}),u("pop push shift sort splice unshift".split(" "),function(n){var t=ui[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);On.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){ +var u=this.value();return t.apply(af(u)?u:[],n)}return this[r](function(r){return t.apply(af(r)?r:[],n)})}}),Et(Mn.prototype,function(n,t){var r=On[t];if(r){var e=r.name+"";(Ji[e]||(Ji[e]=[])).push({name:t,func:r})}}),Ji[Xr(F,2).name]=[{name:"wrapper",func:F}],Mn.prototype.clone=function(){var n=new Mn(this.__wrapped__);return n.__actions__=Mr(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Mr(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Mr(this.__views__), +n},Mn.prototype.reverse=function(){if(this.__filtered__){var n=new Mn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},Mn.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=af(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c=this.__values__.length;return{done:n,value:n?F:this.__values__[this.__index__++]}},On.prototype.plant=function(n){for(var t,r=this;r instanceof Sn;){var e=Pe(r);e.__index__=0,e.__values__=F,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},On.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Mn?(this.__actions__.length&&(n=new Mn(this)),n=n.reverse(),n.__actions__.push({func:nu,args:[Je],thisArg:F}),new zn(n,this.__chain__)):this.thru(Je); +},On.prototype.toJSON=On.prototype.valueOf=On.prototype.value=function(){return kr(this.__wrapped__,this.__actions__)},On.prototype.first=On.prototype.head,Ai&&(On.prototype[Ai]=tu),On}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=it, define(function(){return it})):Vn?((Vn.exports=it)._=it,qn._=it):Zn._=it}).call(this); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js b/vid-app-common/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js new file mode 100644 index 000000000..b9be2c7e4 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/external/multiselect/angular-bootstrap-multiselect.min.js @@ -0,0 +1 @@ +!function(){"use strict";var a=angular.module("btorfs.multiselect",["btorfs.multiselect.templates"]);a.getRecursiveProperty=function(a,b){return b.split(".").reduce(function(a,b){return a?a[b]:null},a)},a.directive("multiselect",["$filter","$document","$log",function(b,c,d){return{restrict:"AE",scope:{options:"=",displayProp:"@",idProp:"@",searchLimit:"=?",selectionLimit:"=?",showSelectAll:"=?",showUnselectAll:"=?",showSearch:"=?",searchFilter:"=?",disabled:"=?ngDisabled",labels:"=?",showTooltip:"=?",placeholder:"@?"},require:"ngModel",templateUrl:"multiselect.html",link:function(b,e,f,g){b.selectionLimit=b.selectionLimit||0,b.searchLimit=b.searchLimit||25,b.searchFilter="",b.resolvedOptions=[],"function"!=typeof b.options&&(b.resolvedOptions=b.options),"undefined"!=typeof f.disabled&&(b.disabled=!0);var h=function(a){e[0].contains(a.target)||b.$apply(function(){b.open=!1})};c.on("click",h);var i=function(){g.$viewValue?(b.selectedOptions=b.resolvedOptions.filter(function(a){for(var c=b.getId(a),d=0;d1){var a=angular.isDefined(b.selectedOptions)?b.selectedOptions.length:0;return 0===a?b.labels&&b.labels.select?b.labels.select:b.placeholder||"Select":a+" "+(b.labels&&b.labels.itemsSelected?b.labels.itemsSelected:"selected")}return b.labels&&b.labels.select?b.labels.select:b.placeholder||"Select"},b.selectAll=function(){b.selectedOptions=b.resolvedOptions.slice(),b.unselectedOptions=[]},b.unselectAll=function(){b.selectedOptions=[],b.unselectedOptions=b.resolvedOptions.slice()},b.toggleItem=function(a){"undefined"==typeof b.selectedOptions&&(b.selectedOptions=[]);var c=b.selectedOptions.indexOf(a),d=c!==-1;if(d)b.unselectedOptions.push(b.selectedOptions[c]),b.selectedOptions.splice(c,1);else if(!d&&(0===b.selectionLimit||b.selectedOptions.lengthb.searchLimit)return!1;var d=b.getDisplay(c);if(d){var e=d.toLowerCase().indexOf(b.searchFilter.toLowerCase())>-1;return e&&a++,e}}}}}}])}(),angular.module("btorfs.multiselect.templates",["multiselect.html"]),angular.module("multiselect.html",[]).run(["$templateCache",function(a){a.put("multiselect.html",'\n')}]); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/images/Calendar.svg b/vid-app-common/src/main/webapp/app/vid/images/Calendar.svg new file mode 100644 index 000000000..23090539e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/images/Calendar.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/images/Calendar_blue.svg b/vid-app-common/src/main/webapp/app/vid/images/Calendar_blue.svg new file mode 100644 index 000000000..f5ac20b2b --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/images/Calendar_blue.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js b/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js index f88ee9c35..534cee505 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js @@ -20,7 +20,9 @@ "use strict"; -appDS2.constant("COMPONENT", (function() { +appDS2 + .constant("_", window._) + .constant("COMPONENT", (function() { return { A_LA_CARTE : "a la carte", CLOUD_REGION_ID : "cloudRegionID", @@ -95,16 +97,30 @@ appDS2.constant("COMPONENT", (function() { VPN_ID_1 : "1a2b3c4d5e6f", // PATHS + GET_WORKFLOW: "change-management/workflow?vnfs=@vnfs", + GET_MSO_WORKFLOWS: "change-management/mso", + GET_SCHEDULER_CHANGE_MANAGEMENTS: "change-management/scheduler", ASSIGN : "?r=", AAI_GET_SERVICE_INSTANCE_PATH : "aai_get_service_instance/", AAI_GET_SERVICES : "aai_get_services", AAI_GET_AIC_ZONES :"aai_get_aic_zones", + AAI_GET_AIC_ZONE_FOR_PNF :"aai_get_aic_zone_for_pnf/@globalCustomerId/@serviceType/@serviceInstanceId", AAI_GET_SERVICES_BY_TYPE : "aai_get_models_by_service_type", AAI_GET_TENANTS : "aai_get_tenants/", AAI_SUB_DETAILS_PATH : "aai_sub_details/", + AAI_GET_VERSION_BY_INVARIANT_ID:"aai_get_version_by_invariant_id/", + AAI_GET_VNF_DATA_PATH: "aai_get_vnf_data/", + AAI_GET_VNF_BY_CUSTOMERID_AND_SERVICETYPE: "get_vnf_data_by_globalid_and_service_type/", AAI_SUB_VIEWEDIT_PATH : "aai_sub_viewedit", + AAI_GET_VNF_INFO : "aai_get_vnf_information", ASDC_GETMODEL_PATH : "asdc/getModel/", CREATE_INSTANCE_PATH : "/models/services/createInstance", + //1710 scheduler contants + POST_CREATE_NEW_VNF_CHANGE:"post_create_new_vnf_change", + GET_POLICY:"get_policy", + GET_TIME_SLOTS:"get_time_slots", + SUBMIT_VNF_CHANGE_TIMESLOTS:"submit_vnf_change_timeslots", + FORWARD_SLASH : "/", GET_SYSTEM_PROP_VNF_PROV_STATUS_PATH : "get_system_prop_vnf_prov_status", GET_USER_ID : "getuserID", @@ -116,6 +132,7 @@ appDS2.constant("COMPONENT", (function() { MSO_CREATE_NW_INSTANCE_PATH : "mso_create_nw_instance/", MSO_CREATE_SVC_INSTANCE : "mso_create_svc_instance", MSO_DELETE_SVC_INSTANCE_PATH : "mso_delete_svc_instance/", + MSO_ACTIVATE_INSTANCE: "mso/mso_activate_service_instance/@serviceInstanceId", SELECTED_SERVICE_SUB_PATH : "#/instances/subdetails?selectedServiceSubscription=", SELECTED_SUB_PATH : "#/instances/subdetails?selectedSubscriber=", SELECTEDSERVICEINSTANCE_SUB_PATH : "&selectedServiceInstance=", @@ -154,6 +171,13 @@ appDS2.constant("COMPONENT", (function() { "vfmodule" : "VF Module", "vnf" : "VNF", "volumegroup" : "Volume Group" + }, + + MANUAL_TASKS: { + "retry": "retry", + "rollback": "rollback", + "abort": "abort", + "skip": "skip" } }; diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/constants/fieldConstants.js b/vid-app-common/src/main/webapp/app/vid/scripts/constants/fieldConstants.js index 9d337fa11..9e3f44cc2 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/constants/fieldConstants.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/constants/fieldConstants.js @@ -31,7 +31,7 @@ appDS2.factory("FIELD", ["PARAMETER", function (PARAMETER) { LCP_REGION: "lcpRegion", LCP_REGION_TEXT: "lcpRegionText", PRODUCT_FAMILY: "productFamily", - AIC_ZONES : "aic_zone", + AIC_ZONES: "aic_zone", SERVICE_TYPE: "serviceType", SERVICE_ROLE: "serviceRole", SUBSCRIBER_NAME: "subscriberName", @@ -127,8 +127,8 @@ appDS2.factory("FIELD", ["PARAMETER", function (PARAMETER) { SDN_C_PRELOAD: "sdncPreload", UPLOAD_SUPPLEMENTORY_DATA_FILE: "uploadSupplementoryDataFile", SUPPLEMENTORY_DATA_FILE: "supplementoryDataFile", - ZONE_ID:"zone-id", - ZONE_NAME:"zone-name", + ZONE_ID: "zone-id", + ZONE_NAME: "zone-name", }; @@ -140,57 +140,58 @@ appDS2.factory("FIELD", ["PARAMETER", function (PARAMETER) { * NAME values are displayed on GUI pages. */ var NAME = { - AVAILABLE_VOLUME_GROUP : "Available Volume Group", - INSTANCE_NAME : "Instance Name", - CUSTOMER_ID : "Customer ID", - LCP_REGION : "LCP Region", - LCP_REGION_TEXT : "Legacy Region", - MODEL_INVARIANT_UUID: "Model Invariant UUID", - MODEL_NAME: "Model Name", - MODEL_VERSION: "Model Version", - MODEL_UUID: "Model UUID", - MODEL_CUSTOMIZATION_UUID: "Model Customization UUID", - MODEL_VNF_TYPE: "NF Type", - MODEL_VNF_ROLE: "NF Role", - MODEL_VNF_FUNCTION: "NF Function", - MODEL_VNF_CODE: "NF Naming Code", - MODEL_CUSTOMIZATION_NAME: "Resource Name", - PRODUCT_FAMILY : "Product Family", + AVAILABLE_VOLUME_GROUP: "Available Volume Group", + INSTANCE_NAME: "Instance Name", + CUSTOMER_ID: "Customer ID", + LCP_REGION: "LCP Region", + LCP_REGION_TEXT: "Legacy Region", + MODEL_INVARIANT_UUID: "Model Invariant UUID", + MODEL_NAME: "Model Name", + MODEL_VERSION: "Model Version", + MODEL_UUID: "Model UUID", + MODEL_CUSTOMIZATION_UUID: "Model Customization UUID", + MODEL_VNF_TYPE: "NF Type", + MODEL_VNF_ROLE: "NF Role", + MODEL_VNF_FUNCTION: "NF Function", + MODEL_VNF_CODE: "NF Naming Code", + MODEL_CUSTOMIZATION_NAME: "Resource Name", + PRODUCT_FAMILY: "Product Family", AIC_ZONES: "AIC Zone", - RESOURCE_DESCRIPTION : "Resource Description", - RESOURCE_NAME : "Resource Name", - SERVICE_CATEGORY : "Service Category", - SERVICE_DESCRIPTION : "Service Description", - SERVICE_INSTANCE_ID : "Service Instance ID", - SERVICE_INSTANCE_Id : "Service Instance Id", - SERVICE_INSTANCE_NAME : "Service Instance Name", - SERVICE_INVARIANT_UUID : "Service Invariant UUID", - SERVICE_NAME : "Service Name", - SERVICE_TYPE : "Service Type", - SERVICE_UUID : "Service UUID", - SERVICE_VERSION : "Service Version", - SUBSCRIBER_NAME : "Subscriber Name", - MOBILITY : "Mobility", - SUPPRESS_ROLLBACK : "Suppress Rollback on Failure", - SDN_C_PRELOAD : "SDN-C Pre-Load", - UPLOAD_SUPPLEMENTORY_DATA_FILE : "Upload Supplementary Data file", - SUPPLEMENTORY_DATA_FILE : "Supplementory Data file (JSON format)", - TENANT : "Tenant", - USER_SERVICE_INSTANCE_NAME : "User Service Instance Name", - VF_MODULE_DESCRIPTION : "VF Module Description", - VF_MODULE_LABEL : "VF Module Label", - VF_MODULE_TYPE : "VF Module Type", - VNF_ORCHESTRATION_STATUS : "Orchestration Status", - VNF_Operational_Status: "Operational Status", - VNF_Current_Prov_Status: "Current Prov_Status", - VNF_Target_Prov_Status: "Target Prov Status", - VNF_VNF_ID : "VNF ID", - VNF_VNF_Name: "VNF Name", - VNF_VNF_Type: "VNF Type", - VNF_Service_ID: "Service ID", - VNF_In_Maint: "In Maint", - VFMDULE_CUSTOMIZATIONUUID: "VF Module Model Customization UUID", - RESOURCE_CUSTOMIZATION_UUID: "Resource Model Customization UUID" + RESOURCE_DESCRIPTION: "Resource Description", + RESOURCE_NAME: "Resource Name", + SERVICE_CATEGORY: "Service Category", + SERVICE_DESCRIPTION: "Service Description", + SERVICE_INSTANCE_ID: "Service Instance ID", + SERVICE_INSTANCE_Id: "Service Instance Id", + SERVICE_INSTANCE_NAME: "Service Instance Name", + SERVICE_INVARIANT_UUID: "Service Invariant UUID", + SERVICE_NAME: "Service Name", + SERVICE_TYPE: "Service Type", + SERVICE_ROLE: "Service Role", + SERVICE_UUID: "Service UUID", + SERVICE_VERSION: "Service Version", + SUBSCRIBER_NAME: "Subscriber Name", + MOBILITY: "Mobility", + SUPPRESS_ROLLBACK: "Suppress Rollback on Failure", + SDN_C_PRELOAD: "SDN-C Pre-Load", + UPLOAD_SUPPLEMENTORY_DATA_FILE: "Upload Supplementary Data file", + SUPPLEMENTORY_DATA_FILE: "Supplementory Data file (JSON format)", + TENANT: "Tenant", + USER_SERVICE_INSTANCE_NAME: "User Service Instance Name", + VF_MODULE_DESCRIPTION: "VF Module Description", + VF_MODULE_LABEL: "VF Module Label", + VF_MODULE_TYPE: "VF Module Type", + VNF_ORCHESTRATION_STATUS: "Orchestration Status", + VNF_Operational_Status: "Operational Status", + VNF_Current_Prov_Status: "Current Prov_Status", + VNF_Target_Prov_Status: "Target Prov Status", + VNF_VNF_ID: "VNF ID", + VNF_VNF_Name: "VNF Name", + VNF_VNF_Type: "VNF Type", + VNF_Service_ID: "Service ID", + VNF_In_Maint: "In Maint", + VFMDULE_CUSTOMIZATIONUUID: "VF Module Model Customization UUID", + RESOURCE_CUSTOMIZATION_UUID: "Resource Model Customization UUID" }; /* @@ -267,29 +268,29 @@ appDS2.factory("FIELD", ["PARAMETER", function (PARAMETER) { } var ERROR = { - AAI : "A&AI failure - see log below for details", - AAI_ERROR : "A&AI Error", - AAI_FETCHING_CUST_DATA : "Failed to fetch customer data from A&AI: Response Code: ", - FETCHING_SERVICE_TYPES : "Failed to fetch service types from A&AI: Response Code: ", - FETCHING_SERVICES : "Failed to fetch services from A&AI: Response Code: ", - FETCHING_SERVICE_INSTANCE_DATA : "Failed to fetch service instance data from A&AI: Response Code: ", - INVALID_INSTANCE_NAME : "Invalid instance name: ", - INSTANCE_NAME_VALIDATE : "The instance name must contain only alphanumeric or \"_-.\" characters, and must start with an alphabetic character", - INVALID_LIST : "Invalid list parameter: ", - INVALID_MAP : "Invalid map parameter: ", - LIST_VALIDATE : "A list parameter value must have the following syntax: '[,\.\.\.,]'", - MAP_VALIDATE : "A map parameter value must have the following syntax: '{ : , \.\.\., : }'", - MAX_POLLS_EXCEEDED : "Maximum number of poll attempts exceeded", - MISSING_DATA : "Missing data", - MODEL_VERSION_ID_MISSING : "Error: model-version-id is not populated in A&AI", - MSO : "MSO failure - see log below for details", - NO_MATCHING_MODEL : "No matching model found matching the persona Model Id = ", - NO_MATCHING_MODEL_AAI : "No matching model found matching the A&AI model version ID = ", - SELECT : "Please select a subscriber or enter a service instance", - SERVICE_INST_DNE : "That service instance does not exist. Please try again.", - SYSTEM_FAILURE : "System failure", - INVALID_DATA_FORMAT : 'Invalid data format.Please check your file content whether it is not in json or not.', - MISSING_FILE : 'Please Select JSON File.', + AAI: "A&AI failure - see log below for details", + AAI_ERROR: "A&AI Error", + AAI_FETCHING_CUST_DATA: "Failed to fetch customer data from A&AI: Response Code: ", + FETCHING_SERVICE_TYPES: "Failed to fetch service types from A&AI: Response Code: ", + FETCHING_SERVICES: "Failed to fetch services from A&AI: Response Code: ", + FETCHING_SERVICE_INSTANCE_DATA: "Failed to fetch service instance data from A&AI: Response Code: ", + INVALID_INSTANCE_NAME: "Invalid instance name: ", + INSTANCE_NAME_VALIDATE: "The instance name must contain only alphanumeric or \"_-.\" characters, and must start with an alphabetic character", + INVALID_LIST: "Invalid list parameter: ", + INVALID_MAP: "Invalid map parameter: ", + LIST_VALIDATE: "A list parameter value must have the following syntax: '[,\.\.\.,]'", + MAP_VALIDATE: "A map parameter value must have the following syntax: '{ : , \.\.\., : }'", + MAX_POLLS_EXCEEDED: "Maximum number of poll attempts exceeded", + MISSING_DATA: "Missing data", + MODEL_VERSION_ID_MISSING: "Error: model-version-id is not populated in A&AI", + MSO: "MSO failure - see log below for details", + NO_MATCHING_MODEL: "No matching model found matching the persona Model Id = ", + NO_MATCHING_MODEL_AAI: "No matching model found matching the A&AI model version ID = ", + SELECT: "Please select a subscriber or enter a service instance", + SERVICE_INST_DNE: "That service instance does not exist. Please try again.", + SYSTEM_FAILURE: "System failure", + INVALID_DATA_FORMAT: 'Invalid data format.Please check your file content whether it is not in json or not.', + MISSING_FILE: 'Please Select JSON File.', } diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/constants/vidConfiguration.js b/vid-app-common/src/main/webapp/app/vid/scripts/constants/vidConfiguration.js index 4341a4cac..ee33875b9 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/constants/vidConfiguration.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/constants/vidConfiguration.js @@ -84,6 +84,10 @@ appDS2.constant("VIDCONFIGURATION", (function() { * Number of msecs that VID will wait between MSO polls. */ var MSO_POLLING_INTERVAL_MSECS = 10000; + + var SCHEDULER_POLLING_INTERVAL_MSECS = 10000; + + var SCHEDULER_MAX_POLLS = 10; /* * List of all service model invariant UUIDs that need macro instantiation. * Example: @@ -91,14 +95,16 @@ appDS2.constant("VIDCONFIGURATION", (function() { * */ var COMPONENT_LIST_NAMED_QUERY_ID = "0367193e-c785-4d5f-9cb8-7bc89dc9ddb7"; - var MACRO_SERVICES = ["93150ffa-00c6-4ea0-85f2-3536ca46ebd2", + var MACRO_SERVICES = ["c9514b73-3dfe-4d7e-9146-b318d48655d9", "93150ffa-00c6-4ea0-85f2-3536ca46ebd2", "2b54297f-72e7-4a94-b451-72df88d0be0b", "d27e42cf-087e-4d31-88ac-6c4b7585f800", - "ec0c4bab-c272-4dab-b087-875031bb0c9f","0311f998-9268-4fd6-bbba-afff15087b72"]; + "ec0c4bab-c272-4dab-b087-875031bb0c9f","0311f998-9268-4fd6-bbba-afff15087b72","43596836-ae36-4608-a987-6608ede10dac","306caa85-74c7-48a9-aa22-7e3a564b957a"]; return { ASDC_MODEL_STATUS : ASDC_MODEL_STATUS, MSO_MAX_POLLS : MSO_MAX_POLLS, MSO_POLLING_INTERVAL_MSECS : MSO_POLLING_INTERVAL_MSECS, + SCHEDULER_MAX_POLLS : SCHEDULER_MAX_POLLS, + SCHEDULER_POLLING_INTERVAL_MSECS : SCHEDULER_POLLING_INTERVAL_MSECS, VNF_STATUS_CHECK_ENABLED : VNF_STATUS_CHECK_ENABLED, VNF_VALID_STATUS_LIST : vnfValidStatusList, UPLOAD_SUPPLEMENTARY_STATUS_CHECK_ENABLED : UPLOAD_SUPPLEMENTARY_STATUS_CHECK_ENABLED, diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js index b0fcb11e2..f0653f680 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js @@ -352,9 +352,6 @@ $scope.deleteVnf = function(serviceObject, vnf) { - - debugger; - console.log("Removing VNF " + vnf.name); var serviceInstance = serviceObject.object; diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js index 731c2f2e8..a0030889a 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js @@ -39,8 +39,8 @@ $http.get(pathQuery) .then(function successCallback(response) { $scope.services = []; - if (angular.isArray(response.data.services)) { - wholeData = response.data.services; + if (angular.isArray(response.data)) { + wholeData = response.data; $scope.services = $scope.filterDataWithHigerVersion(wholeData); $scope.viewPerPage=10; $scope.totalPage=$scope.services.length/$scope.viewPerPage; diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/VidApp.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/VidApp.js index dcde2ecc6..b611def42 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/VidApp.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/VidApp.js @@ -47,6 +47,11 @@ templateUrl : "app/vid/scripts/view-models/aaiSubDetails.htm", controller : "aaiSubscriberController" }) + .when('/change-management', { + templateUrl : "app/vid/scripts/view-models/change-management.html", + controller : "changeManagementController", + controllerAs: 'vm' + }) .when('/instantiate', { controller: 'InstantiationController', templateUrl: 'app/vid/scripts/view-models/instantiate.htm' diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js index 84d27a230..6bf16c349 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/aaiSubscriberController.js @@ -20,8 +20,8 @@ "use strict"; -appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", "DataService", "PropertyService", "$scope", "$http", "$timeout", "$location", "$log", "$route", "VIDCONFIGURATION", "UtilityService", "vidService", "AaiService", - function (COMPONENT, FIELD, PARAMETER, DataService, PropertyService, $scope, $http, $timeout, $location, $log, $route, VIDCONFIGURATION, UtilityService, vidService, AaiService) { +appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", "DataService", "PropertyService", "$scope", "$http", "$timeout", "$location", "$log", "$route", "VIDCONFIGURATION", "UtilityService", "vidService", "AaiService", "MsoService", + function (COMPONENT, FIELD, PARAMETER, DataService, PropertyService, $scope, $http, $timeout, $location, $log, $route, VIDCONFIGURATION, UtilityService, vidService, AaiService, MsoService) { $scope.showVnfDetails = function (vnf) { console.log("showVnfDetails"); @@ -901,6 +901,17 @@ appDS2.controller("aaiSubscriberController", ["COMPONENT", "FIELD", "PARAMETER", $scope.currentPage--; } + $scope.activateMSOInstance = function() { + MsoService.activateInstance($scope.service.instance, $scope.service.model) + .then(function(response) { + alert("Activation succeeded"); + }) + .catch(function (error) { + $log.error(error); + }); + ; + }; + $scope.nextPage = function () { $scope.currentPage++; } diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/controller/change-management.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/controller/change-management.controller.js new file mode 100644 index 000000000..662b10ecd --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/controller/change-management.controller.js @@ -0,0 +1,138 @@ +(function () { + 'use strict'; + + appDS2.controller("changeManagementController", ["$uibModal", "changeManagementService", "_", "$log", changeManagementController]); + + function changeManagementController($uibModal, changeManagementService, _, $log) { + var vm = this; + + var init = function() { + loadMSOChangeManagements(); + loadSchedulerChangeManagements(); + }; + + var loadMSOChangeManagements = function() { + changeManagementService.getMSOChangeManagements() + .then(function(response) { + vm.changeManagements = response.data; + }) + .catch(function (error) { + $log.error(error); + }); + }; + + var loadSchedulerChangeManagements = function() { + changeManagementService.getSchedulerChangeManagements() + .then(function(response) { + vm.pendingChangeManagements = response.data; + _.forEach(vm.pendingChangeManagements, function(changeManagement) { + var callbackData = _.filter(changeManagement.scheduleRequest.domainData, {name: "CallbackData"}); + if(callbackData) { + var parsedModel = {}; + try { + parsedModel = JSON.parse(callbackData[0].value); + } catch(exception) { + $log.error(exception); + } + + changeManagement.workflow = parsedModel.requestType || 'No workflow'; + } + }); + }) + .catch(function(error) { + $log.error(error); + }); + }; + + vm.createNewChange = function() { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/new-change-management/new-change-management.html', + controller: 'newChangeManagementModalController', + controllerAs: 'vm', + resolve: {} + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the new change management modal.", result); + }); + }; + + vm.openScheduler = function() { + console.log("function for opening the scheduler app") + }; + + vm.searchChanges = function() { + console.log("function for searching changes: " + vm.searchChangesTerm) + }; + + vm.openFailedModal = function(jobInfo) { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/failed-change-management/failed-change-management.html', + controller: 'changeManagementManualTasksController', + controllerAs: 'vm', + resolve: { + jobInfo: function () { + return jobInfo; + } + } + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the failed change management modal.", result); + }); + }; + + vm.openInProgressModal = function(jobInfo) { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.html', + controller: 'changeManagementManualTasksController', + controllerAs: 'vm', + resolve: { + jobInfo: function () { + return jobInfo; + } + } + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the in progress change management modal.", result); + }); + }; + + vm.openAlertModal = function(jobInfo) { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/alert-change-management/alert-change-management.html', + controller: 'changeManagementManualTasksController', + controllerAs: 'vm', + resolve: { + jobInfo: function () { + return jobInfo; + } + } + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the alert change management modal.", result); + }); + }; + + vm.openPendingModal = function(jobInfo) { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/pending-change-management/pending-change-management.html', + controller: 'changeManagementManualTasksController', + controllerAs: 'vm', + resolve: { + jobInfo: function () { + return jobInfo; + } + } + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the pending change management modal.", result); + }); + }; + + init(); + } +})(); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/directives/angularjs-datetime-picker.js b/vid-app-common/src/main/webapp/app/vid/scripts/directives/angularjs-datetime-picker.js new file mode 100644 index 000000000..b80b4cdae --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/directives/angularjs-datetime-picker.js @@ -0,0 +1,361 @@ + + 'use strict'; + + + + var getTimezoneOffset = function(date) { + (typeof date == 'string') && (date = new Date(date)); + var jan = new Date(date.getFullYear(), 0, 1); + var jul = new Date(date.getFullYear(), 6, 1); + var stdTimezoneOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); + var isDST = date.getTimezoneOffset() < stdTimezoneOffset; + var offset = isDST ? stdTimezoneOffset - 60 : stdTimezoneOffset; + var diff = offset >=0 ? '-' : '+'; + return diff + + ("0"+ (offset / 60)).slice(-2) + ':' + + ("0"+ (offset % 60)).slice(-2); + }; + + var DatetimePicker = function($compile, $document, $controller){ + var datetimePickerCtrl = $controller('DatetimePickerCtrl'); //directive controller + return { + open: function(options) { + datetimePickerCtrl.openDatetimePicker(options); + }, + close: function() { + datetimePickerCtrl.closeDatetimePicker(); + } + }; + }; + DatetimePicker.$inject = ['$compile', '$document', '$controller']; + appDS2.factory('DatetimePicker', DatetimePicker); + + var DatetimePickerCtrl = function($compile, $document) { + var datetimePickerEl; + var _this = this; + var removeEl = function(el) { + el && el.remove(); + $document[0].body.removeEventListener('click', _this.closeDatetimePicker); + }; + + this.openDatetimePicker = function(options) { + this.closeDatetimePicker(); + var div = angular.element('
'); + options.dateFormat && div.attr('date-format', options.dateFormat); + options.ngModel && div.attr('ng-model', options.ngModel); + options.year && div.attr('year', parseInt(options.year)); + options.month && div.attr('month', parseInt(options.month)); + options.day && div.attr('day', parseInt(options.day)); + options.hour && div.attr('hour', parseInt(options.hour)); + options.minute && div.attr('minute', parseInt(options.minute)); + if (options.dateOnly === '' || options.dateOnly === true) { + div.attr('date-only', 'true'); + } + if (options.closeOnSelect === 'false') { + div.attr('close-on-select', 'false'); + } + + var triggerEl = options.triggerEl; + options.scope = options.scope || angular.element(triggerEl).scope(); + datetimePickerEl = $compile(div)(options.scope)[0]; + datetimePickerEl.triggerEl = options.triggerEl; + + $document[0].body.appendChild(datetimePickerEl); + + //show datetimePicker below triggerEl + var bcr = triggerEl.getBoundingClientRect(); + + + options.scope.$apply(); + + var datePickerElBcr = datetimePickerEl.getBoundingClientRect(); + + datetimePickerEl.style.position='absolute'; + if(bcr.width > datePickerElBcr.width){ + datetimePickerEl.style.left= (bcr.left + bcr.width - datePickerElBcr.width + window.scrollX) + 'px'; + } else { + datetimePickerEl.style.left= (bcr.left + window.scrollX) + 'px'; + } + + if (bcr.top < 300 || window.innerHeight - bcr.bottom > 300) { + datetimePickerEl.style.top = (bcr.bottom + window.scrollY) + 'px'; + } else { + datetimePickerEl.style.top = (bcr.top - datePickerElBcr.height + window.scrollY) + 'px'; + } + + $document[0].body.addEventListener('click', this.closeDatetimePicker); + }; + + this.closeDatetimePicker = function(evt) { + var target = evt && evt.target; + var popupEl = $document[0].querySelector('div[datetime-picker-popup]'); + if (evt && target) { + if (target.hasAttribute('datetime-picker')) { // element with datetimePicker behaviour + // do nothing + } else if (popupEl && popupEl.contains(target)) { // datetimePicker itself + // do nothing + } else { + removeEl(popupEl); + } + } else { + removeEl(popupEl); + } + } + }; + DatetimePickerCtrl.$inject = ['$compile', '$document']; + appDS2.controller('DatetimePickerCtrl', DatetimePickerCtrl); + + var tmpl = [ + '
' , + '
', + ' ', + ' {{months[mv.month].shortName}} {{mv.year}}', + ' ', + '
', + '
', + '
{{::dayOfWeek.firstLetter}}
', + '
{{::day}}
', + '
', + ' {{::day}}', + '
', + '
{{::day}}
', + '
', + '
', + ' {{("0"+inputHour).slice(-2)}} : {{("0"+inputMinute).slice(-2)}}
', + ' ', + ' ', + '
', + '
'].join("\n"); + + var datetimePickerPopup = function($locale, dateFilter){ + var days, months, daysOfWeek, firstDayOfWeek; + + var initVars = function() { + days =[], months=[]; daysOfWeek=[], firstDayOfWeek=0; + for (var i = 1; i <= 31; i++) { + days.push(i); + } + + for (var i = 0; i < 12; i++) { //jshint ignore:line + months.push({ + fullName: $locale.DATETIME_FORMATS.MONTH[i], + shortName: $locale.DATETIME_FORMATS.SHORTMONTH[i] + }); + } + + for (var i = 0; i < 7; i++) { //jshint ignore:line + var day = $locale.DATETIME_FORMATS.DAY[(i + firstDayOfWeek) % 7]; + + daysOfWeek.push({ + fullName: day, + firstLetter: day.substr(0, 1) + }); + } + firstDayOfWeek = 0; + }; + + var getMonthView = function(year, month) { + if (month>11) { + year++; + } else if (month < 0) { + year--; + } + month = (month + 12) % 12; + var firstDayOfMonth = new Date(year, month, 1), + lastDayOfMonth = new Date(year, month + 1, 0), + lastDayOfPreviousMonth = new Date(year, month, 0), + daysInMonth = lastDayOfMonth.getDate(), + daysInLastMonth = lastDayOfPreviousMonth.getDate(), + dayOfWeek = firstDayOfMonth.getDay(), + leadingDays = (dayOfWeek - firstDayOfWeek + 7) % 7 || 7, // Ensure there are always leading days to give context + trailingDays = days.slice(0, 6 * 7 - (leadingDays + daysInMonth)); + if (trailingDays.length > 7) { + trailingDays = trailingDays.slice(0, trailingDays.length-7); + } + + return { + year: year, + month: month, + days: days.slice(0, daysInMonth), + leadingDays: days.slice(- leadingDays - (31 - daysInLastMonth), daysInLastMonth), + trailingDays: trailingDays + }; + }; + + var linkFunc = function(scope, element, attrs, ctrl) { //jshint ignore:line + initVars(); //initialize days, months, daysOfWeek, and firstDayOfWeek; + var dateFormat = attrs.dateFormat || 'short'; + scope.months = months; + scope.daysOfWeek = daysOfWeek; + scope.inputHour; + scope.inputMinute; + + if (scope.dateOnly === true){ + element[0].querySelector('#adp-time').style.display = 'none'; + } + + scope.$applyAsync( function() { + ctrl.triggerEl = angular.element(element[0].triggerEl); + if (attrs.ngModel) { // need to parse date string + var dateStr = ''+ctrl.triggerEl.scope().$eval(attrs.ngModel); + if (dateStr) { + if (!dateStr.match(/[0-9]{2}:/)) { // if no time is given, add 00:00:00 at the end + dateStr += " 00:00:00"; + } + dateStr = dateStr.replace(/([0-9]{2}-[0-9]{2})-([0-9]{4})/,'$2-$1'); //mm-dd-yyyy to yyyy-mm-dd + dateStr = dateStr.replace(/([\/-][0-9]{2,4})\ ([0-9]{2}\:[0-9]{2}\:)/,'$1T$2'); //reformat for FF + dateStr = dateStr.replace(/EDT|EST|CDT|CST|MDT|PDT|PST|UT|GMT/g,''); //remove timezone + dateStr = dateStr.replace(/\s*\(\)\s*/,''); //remove timezone + dateStr = dateStr.replace(/[\-\+][0-9]{2}:?[0-9]{2}$/,''); //remove timezone + dateStr += getTimezoneOffset(dateStr); + var d = new Date(dateStr); + scope.selectedDate = new Date( + d.getFullYear(), + d.getMonth(), + d.getDate(), + d.getHours(), + d.getMinutes(), + d.getSeconds() + ); + } + } + + if (!scope.selectedDate || isNaN(scope.selectedDate.getTime())) { // no predefined date + var today = new Date(); + var year = scope.year || today.getFullYear(); + var month = scope.month ? (scope.month-1) : today.getMonth(); + var day = scope.day || today.getDate(); + var hour = scope.hour || today.getHours(); + var minute = scope.minute || today.getMinutes(); + scope.selectedDate = new Date(year, month, day, hour, minute, 0); + } + scope.inputHour = scope.selectedDate.getHours(); + scope.inputMinute = scope.selectedDate.getMinutes(); + + // Default to current year and month + scope.mv = getMonthView(scope.selectedDate.getFullYear(), scope.selectedDate.getMonth()); + scope.today = dateFilter(new Date(), 'yyyy-M-d'); + if (scope.mv.year == scope.selectedDate.getFullYear() && scope.mv.month == scope.selectedDate.getMonth()) { + scope.selectedDay = scope.selectedDate.getDate(); + } else { + scope.selectedDay = null; + } + }); + +/* disable previous months.not current months + scope.addMonth = function (amount) { + var today = new Date(); + if((amount==-1) && (scope.mv.month==today.getMonth())){ + + + } + else{ + + scope.mv = getMonthView(scope.mv.year, scope.mv.month + amount); + } + };*/ + + scope.addMonth = function (amount) { + scope.mv = getMonthView(scope.mv.year, scope.mv.month + amount); + }; + + scope.setDate = function (evt) { + + var target = angular.element(evt.target)[0]; + if (target.className.indexOf('selectable') !== -1) { + scope.updateNgModel(parseInt(target.innerHTML)); + if (scope.closeOnSelect !== false) { + ctrl.closeDatetimePicker(); + } + } + }; + + scope.updateNgModel = function(day) { + day = day ? day : scope.selectedDate.getDate(); + scope.selectedDate = new Date( + scope.mv.year, scope.mv.month, day, scope.inputHour, scope.inputMinute, 0 + ); + scope.selectedDay = scope.selectedDate.getDate(); + if (attrs.ngModel) { + //console.log('attrs.ngModel',attrs.ngModel); + var elScope = ctrl.triggerEl.scope(), dateValue; + if (elScope.$eval(attrs.ngModel) && elScope.$eval(attrs.ngModel).constructor.name === 'Date') { + dateValue = new Date(dateFilter(scope.selectedDate, dateFormat)); + } else { + dateValue = dateFilter(scope.selectedDate, dateFormat); + } + elScope.$eval(attrs.ngModel + '= date', {date: dateValue}); // this line for have the date in the format of mm/dd/yyyy + // elScope.$eval(attrs.ngModel + '= date', {date: scope.selectedDate});// this line in the format of Thu Jul 20 2017 23:59:00 GMT-0400 (Eastern Daylight Time) + } + }; + + scope.$on('$destroy', ctrl.closeDatetimePicker); + }; + + return { + restrict: 'A', + template: tmpl, + controller: 'DatetimePickerCtrl', + replace: true, + scope: { + year: '=', + month: '=', + day: '=', + hour: '=', + minute: '=', + dateOnly: '=', + closeOnSelect: '=', + futureOnly:'=' + }, + link: linkFunc + }; + }; + datetimePickerPopup.$inject = ['$locale', 'dateFilter']; + appDS2.directive('datetimePickerPopup', datetimePickerPopup); + + var datetimePicker = function($parse, DatetimePicker) { + return { + // An ngModel is required to get the controller argument + require: 'ngModel', + link: function(scope, element, attrs, ctrl) { + // Attach validation watcher + scope.$watch(attrs.ngModel, function(value) { + if( !value || value == '' ){ + return; + } + // The value has already been cleaned by the above code + var date = new Date(value); + ctrl.$setValidity('date', !date? false : true); + var now = new Date(); + if( attrs.hasOwnProperty('futureOnly') ){ + ctrl.$setValidity('future-only', date < now? false : true); + } + }); + + element[0].addEventListener('click', function() { + DatetimePicker.open({ + triggerEl: element[0], + dateFormat: attrs.dateFormat, + ngModel: attrs.ngModel, + year: attrs.year, + month: attrs.month, + day: attrs.day, + hour: attrs.hour, + minute: attrs.minute, + dateOnly: attrs.dateOnly, + futureOnly: attrs.futureOnly, + closeOnSelect: attrs.closeOnSelect + }); + }); + } + }; + }; + datetimePicker.$inject=['$parse', 'DatetimePicker']; + appDS2.directive('datetimePicker', datetimePicker); + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/filters/change-managements-by-statuses.filter.js b/vid-app-common/src/main/webapp/app/vid/scripts/filters/change-managements-by-statuses.filter.js new file mode 100644 index 000000000..6f0ae2c69 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/filters/change-managements-by-statuses.filter.js @@ -0,0 +1,22 @@ +(function () { + 'use strict'; + appDS2.filter('changeManagementsByStatuses', [changeManagementsByStatuses]); + + function changeManagementsByStatuses () { + return function(changeManagements, metadata) { + var result = []; + if(changeManagements && metadata && metadata.statuses) { + angular.forEach(changeManagements, function(changeManagement) { + angular.forEach(metadata.statuses, function(status) { + if(changeManagement.requestStatus.requestState === status) { + result.push(changeManagement); + return; + } + }); + }); + } + + return result; + } + } +})(); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/filters/date.filter.js b/vid-app-common/src/main/webapp/app/vid/scripts/filters/date.filter.js new file mode 100644 index 000000000..3b2eb1836 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/filters/date.filter.js @@ -0,0 +1,18 @@ +(function () { + 'use strict'; + appDS2.filter('vidDate', ['$filter', vidDate]); + + function vidDate($filter) { + var suffixes = ["th", "st", "nd", "rd"]; + return function(input, format) { + if(input) { + var dtfilter = $filter('date')(input, format); + var day = parseInt($filter('date')(input, 'dd')); + var relevantDigits = (day < 30) ? day % 20 : day % 30; + var suffix = (relevantDigits <= 3) ? suffixes[relevantDigits] : suffixes[0]; + return dtfilter.replace('oo', suffix); + } + return input; + }; + } +})(); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.css new file mode 100644 index 000000000..316c2e46e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.css @@ -0,0 +1,3 @@ +.modal-header h3 { + border-bottom: 3px solid #ffb81c; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.html new file mode 100644 index 000000000..bdc95c98e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-change-management/alert-change-management.html @@ -0,0 +1,12 @@ + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.controller.js new file mode 100644 index 000000000..2c5eabed9 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.controller.js @@ -0,0 +1,33 @@ +(function () { + 'use strict'; + + appDS2.controller("alertNewSchedulerController", ["$uibModalInstance", "jobInfo", "MsoService", "COMPONENT", + "$log", alertNewSchedulerController]); + + function alertNewSchedulerController($uibModalInstance, jobInfo, MsoService, COMPONENT, $log) { + var vm = this; + + vm.manualTasks = []; + vm.MANUAL_TASKS = COMPONENT.MANUAL_TASKS; + var init = function() { + if (jobInfo) { + vm.content = jobInfo; + } else { + vm.content = "Successfully"; + } + + + + }; + + + + + + vm.close = function () { + $uibModalInstance.close(); + }; + + init(); + } +})(); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.css new file mode 100644 index 000000000..316c2e46e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.css @@ -0,0 +1,3 @@ +.modal-header h3 { + border-bottom: 3px solid #ffb81c; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.html new file mode 100644 index 000000000..e6255cf36 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.html @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.controller.js new file mode 100644 index 000000000..91bac5697 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.controller.js @@ -0,0 +1,56 @@ +(function () { + 'use strict'; + + appDS2.controller("changeManagementManualTasksController", ["$uibModalInstance", "jobInfo", "MsoService", "COMPONENT", + "$log", changeManagementManualTasksController]); + + function changeManagementManualTasksController($uibModalInstance, jobInfo, MsoService, COMPONENT, $log) { + var vm = this; + + vm.manualTasks = []; + vm.MANUAL_TASKS = COMPONENT.MANUAL_TASKS; + var init = function() { + if (jobInfo && jobInfo.details) { + vm.content = jobInfo.details; + } else { + vm.content = "The VNF change alerted due to unknown reason."; + } + + loadAvailableTasks(jobInfo.job.requestId); + + }; + + function loadAvailableTasks(requestId) { + MsoService.getManualTasks(requestId) + .then(function(response) { + vm.task = response.data[0]; + vm.manualTasks = vm.task && vm.task.validResponses; + }) + .catch(function(error) { + $log.error(error); + }); + } + + vm.completeTask = function(task) { + MsoService.completeTask(vm.task.taskId, task) + .then(function(response) { + vm.manualTasks = response.data; + $uibModalInstance.close(task + " action completed successfully."); + }) + .catch(function(error) { + $uibModalInstance.close(task + " action failed."); + $log.error(error); + }); + }; + + vm.close = function () { + $uibModalInstance.close(); + }; + + vm.isTaskAvailable = function(task) { + return vm.manualTasks.includes(task); + }; + + init(); + } +})(); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.html new file mode 100644 index 000000000..687394156 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/change-management-manual-tasks-controller/change-management-manual-tasks.html @@ -0,0 +1,7 @@ +
+ +
+ diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.css new file mode 100644 index 000000000..fb4a06c7b --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.css @@ -0,0 +1,3 @@ +.modal-header h3 { + border-bottom: 3px solid #cf2a2a; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.html new file mode 100644 index 000000000..0deaf93d2 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/failed-change-management/failed-change-management.html @@ -0,0 +1,12 @@ + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.css new file mode 100644 index 000000000..02a0df47e --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.css @@ -0,0 +1,3 @@ +.modal-header h3 { + border-bottom: 3px solid #4ca90c; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.html new file mode 100644 index 000000000..9b40db2a5 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/in-progress-modal-management/in-progress-change-management.html @@ -0,0 +1,12 @@ + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js new file mode 100644 index 000000000..14ca43b56 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.controller.js @@ -0,0 +1,369 @@ +(function () { + 'use strict'; + + appDS2.controller("newChangeManagementModalController", ["$uibModalInstance", "$uibModal", "AaiService", "changeManagementService", + "$log", "$scope", "_", newChangeManagementModalController]); + + function newChangeManagementModalController($uibModalInstance, $uibModal, AaiService, changeManagementService, $log, $scope, _) { + var vm = this; + + var init = function () { + vm.changeManagement = {}; + + loadServicesCatalog(); + registerVNFNamesWatcher(); + vm.loadSubscribers(); + }; + + var loadServicesCatalog = function () { + changeManagementService.getAllSDCServices() + .then(function (response) { + vm.SDCServicesCatalog = response.data; + }) + .catch(function (error) { + $log.error(error); + }) + }; + + var registerVNFNamesWatcher = function () { + $scope.$watch('vm.changeManagement.vnfNames', function (newVal, oldVal) { + if (!oldVal || newVal && newVal.length > oldVal.length) { //JUST THE LAST ONE ADDED + var newVNFName = _.last(vm.changeManagement.vnfNames); + if (oldVal) { + vm.changeManagement.vnfNames = oldVal; + vm.changeManagement.vnfNames.push(newVNFName); + } + if (newVNFName && newVNFName["service-instance-node"]) { + var availableVersions = []; + var services = _.filter(vm.SDCServicesCatalog.services, + {"invariantUUID": newVNFName["service-instance-node"][0].properties["model-invariant-id"]}); + + _.each(services, function (service) { + changeManagementService.getSDCService(service.uuid) + .then(function (response) { + _.each(response.data.vnfs, function (vnf) { + if (newVNFName["invariant-id"] === vnf.invariantUuid) { + availableVersions.push(extractVNFModel(vnf, response.data.service, newVNFName)); + } + }); + var versions = _.uniqBy(availableVersions, ['modelInfo.modelVersion']); + newVNFName.availableVersions = _.uniq(versions, response.data.service, true); + }).catch(function (error) { + $log.error(error); + }); + }); + } + } + }, true); + }; + + var extractVNFModel = function (csarVNF, sdcService, selectionVNF) { + var versionCsarData = { + vnfInstanceId: "", + vnfName: csarVNF.name, + modelInfo: { + modelType: "vnf", + modelInvariantId: csarVNF.invariantUuid, + modelVersionId: selectionVNF.modelVersionId, + modelName: csarVNF.name, + modelVersion: csarVNF.version, + modelCustomizationName: csarVNF.modelCustomizationName, + modelCustomizationId: csarVNF.customizationUuid + }, + cloudConfiguration: { + lcpCloudRegionId: "mdt1", + tenantId: "88a6ca3ee0394ade9403f075db23167e" + }, + requestInfo: { + source: "VID", + suppressRollback: false, + requestorId: "az2016" + }, + relatedInstanceList: [ + { + relatedInstance: { + instanceId: selectionVNF["service-instance-node"]["0"].properties['service-instance-id'], + modelInfo: { + modelType: "service", + modelInvariantId: selectionVNF["service-instance-node"]["0"].properties['model-invariant-id'], + modelVersionId: selectionVNF.modelVersionId, + modelName: sdcService.name, + modelVersion: sdcService.version, + modelCustomizationName: selectionVNF["service-instance-node"]["0"].properties['model-customization-name'], //TODO: Missing + modelCustomizationId: selectionVNF["service-instance-node"]["0"].properties['model-customization-id'] + } + } + } + ], + requestParameters: { + usePreload: true + } + }; + + return versionCsarData; + }; + + vm.close = function () { + $uibModalInstance.close(); + }; + + vm.schedule = function () { + $uibModalInstance.close(vm.changeManagement); + + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/new-scheduler/new-scheduler.html', + controller: 'newSchedulerController', + controllerAs: 'vm', + resolve: { + changeManagement: function () { + return vm.changeManagement; + } + } + }); + + modalInstance.result.then(function (result) { + console.log("This is the result of the new change management modal.", result); + }) + }; + + vm.loadSubscribers = function () { + vm.subscribers = []; + AaiService.getSubscribers(function (response) { + vm.subscribers = response; + }); + }; + + vm.loadServiceTypes = function () { + vm.serviceTypes = []; + + AaiService.getSubscriberServiceTypes(vm.changeManagement.subscriberId) + .then(function (response) { + vm.serviceTypes = response.data; + }) + .catch(function (error) { + $log.error(error); + }); + }; + + vm.loadVNFTypes = function () { + vm.vnfTypes = []; + vm.vnfTypesTemp = []; + vm.serviceInstances = []; + + var instances = vm.changeManagement.serviceType["service-instances"]["service-instance"]; + // var promiseArrOfGetVnfs = preparePromiseArrOfGetVnfs(instances); + + vm.vnfs = []; + + AaiService.getVnfsByCustomerIdAndServiceType( + vm.changeManagement.subscriberId, + vm.changeManagement.serviceType["service-type"] + ).then(function (response) { + var vnfsData = response.data.results; + if (vnfsData) { + for (var i = 0; i < vnfsData.length; i++) { + if (vnfsData[i]) { + const nodeType = vnfsData[i]['node-type']; + if (nodeType === "generic-vnf") { + _.forEach(vnfsData[i]['related-to'], function (node) { + if (node['node-type'] === 'vserver') { + vm.vnfs.push(vnfsData[i]); + } + }) + } else if (nodeType === "service-instance") { + vm.serviceInstances.push(vnfsData[i]); + } + } + } + + vm.vnfs = _.flattenDeep( + _.remove(vm.vnfs, function (vnf) { + var nfRole = vnf.properties['nf-role']; + if (nfRole !== undefined) { + return nfRole !== 'null' && nfRole !== ''; + } + }) + ); + + var filteredVnfs = _.uniqBy(vm.vnfs, function (vnf) { + return vnf.properties['nf-role']; + }); + + _.forEach(filteredVnfs, function (vnf) { + vm.vnfTypes.push(vnf.properties['nf-role']) + }); + } + } + ); + }; + + vm.loadVNFVersions = function () { + vm.fromVNFVersions = []; + vm.serviceInstancesToGetVersions = []; + var versions = []; + _.forEach(vm.vnfs, function (vnf) { + if (vnf.properties['nf-role'] === vm.changeManagement['vnfType']) { + + vm.serviceInstancesToGetVersions.push(vnf); + + versions.push(vnf.properties["model-invariant-id"]); + + + } + }); + + AaiService.getVnfVersionsByInvariantId(versions).then(function (response) { + if (response.data) { + var key = response.data.model["0"]["model-invariant-id"]; + var value = response.data.model["0"]["model-vers"]["model-ver"]["0"]["model-version"]; + var element = {"key": key, "value": value}; + vm.fromVNFVersions.push(element); + } + //TODO promise all and call the new api to get the versions. + // vm.fromVNFVersions.push(response.data.model["0"]["model-vers"]["model-ver"]["0"]["model-version"]); + // if(vm.serviceInstancesToGetVersions.length > 0){ + // + // var promiseArrOfGetVnfs = preparePromiseArrOfGetVersions('a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb'); + // + // Promise.all(promiseArrOfGetVnfs).then(function (allData) { + // vm.vnfs = _.flattenDeep(_.without(allData, null)); + // var filteredVnfs = _.sortedUniqBy(vm.vnfs, function (vnf) { + // return vnf.properties.vnfType; + // }); + // + // _.forEach(filteredVnfs, function (vnf) { + // vm.vnfTypes.push(vnf.properties.vnfType) + // }); + // + // }).catch(function (error) { + // $log(error); + // }); + // } + }) + // debugger; + + }; + + // function preparePromiseArrOfGetVersions(serviceInstances) { + // var promiseArr = []; + // for (var i = 0; i < serviceInstances.length; i++) { + // var modelInvariantId = serviceInstances[i].properties["model-invariant-id"]; + // promiseArr.push( + // getVnfs(modelInvariantId) + // ); + // } + // return promiseArr; + // } + + function getVnfs(modelInvariantId) { + return new Promise(function (resolve, reject) { + AaiService.getVnfVersionsByInvariantId(modelInvariantId) + .then(function (response) { + if (response.data.httpCode !== null && + response.data.httpCode === 200) { + var vnfsData = response.data.t.results; + for (var i = 0; i < vnfsData.length; i++) { + if (vnfsData[i]) { + if (vnfsData[i].nodeType === "generic-vnf") { + resolve(vnfsData[i]); + } else if (vnfsData[i].nodeType === "service-instance") { + vm.serviceInstances.push(vnfsData[i]); + } + } + } + resolve(null); + } + resolve(null); + }) + .catch(function (error) { + reject(error); + }); + }); + } + + vm.loadVNFNames = function () { + vm.vnfNames = []; + + _.forEach(vm.vnfs, function (vnf) { + + if (vnf.properties['nf-role'] === vm.changeManagement.vnfType) { + var vServer = {}; + + _.forEach(vnf['related-to'], function (node) { + if (node['node-type'] === 'vserver') { + vServer = extractLcpRegionIdAndTenantId(node.url); + } + }); + + vm.vnfNames.push({ + "id": vnf.properties["vnf-id"], + "name": vnf.properties["vnf-name"], + "invariant-id": vnf.properties["model-invariant-id"], + "service-instance-node": _.filter(vm.serviceInstances, {id: vnf["related-to"][0].id}), + "modelVersionId": vnf.properties["model-version-id"], + "properties": vnf.properties, + 'cloudConfiguration': vServer, + "relatedTo": vnf['related-to'] + }); + } + }); + }; + + function extractLcpRegionIdAndTenantId(url) { + + var cloudConfiguration = { + lcpCloudRegionId: '', + tenantId: '' + }; + + var splitedUrlByDash = _.split(url, '/', 100); + + cloudConfiguration.lcpCloudRegionId = splitedUrlByDash[7]; + cloudConfiguration.tenantId = splitedUrlByDash[10]; + + return cloudConfiguration; + }; + + vm.loadWorkFlows = function () { + var vnfs = []; + angular.forEach(vm.changeManagement.vnfNames, function (vnfName) { + vnfs.push(vnfName.name) + }); + + //TODO: When we'll have the mappings, use the backend call to get the workflows + // changeManagementService.getWorkflows(vnfs) + // .then(function(response) { + // vm.workflows = response.data; + // }) + // .catch(function(error) { + // $log.error(error); + // }); + + vm.workflows = ["Update", "Replace"]; + }; + + //Must be $scope because we bind to the onchange of the html (cannot attached to vm variable). + $scope.selectFileForVNFName = function (fileInput) { + if (fileInput && fileInput.id) { + var vnfName = _.filter(vm.changeManagement.vnfNames, {"invariant-id": fileInput.id}); + var file = fileInput.files[0]; + var fileReader = new FileReader(); + fileReader.onload = function (load) { + try { + var lines = load.target.result; + vnfName[0].selectedFile = JSON.parse(lines); + } catch (error) { + $log.error(error); + } + }; + fileReader.readAsText(file); + } + }; + + vm.selectVersionForVNFName = function (vnfName) { + console.log("Will add version for selected vnf name: " + vnfName.name); + }; + + init(); + } +})(); \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.css new file mode 100644 index 000000000..9d270987a --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.css @@ -0,0 +1,130 @@ +.btn-white { + font-family: "Open Sans"; + border-radius: 2px; + border: 1px solid #d8d8d8; + background-color: #ffffff; + width: 94px; + height: 30px; + color: #5a5a5a; + font-size: 13px; + font-weight: 400; + line-height: 36px; + text-align: center; + padding: 4px 12px !important; +} + +.btn-primary { + font-family: "Open Sans"; + border-radius: 2px; + border: 1px solid #0091c8; + background-color: #009fdb; + width: 94px; + height: 30px; + color: #ffffff; + font-size: 13px; + font-weight: 400; + line-height: 36px; + text-align: center; + padding: 4px 12px !important; +} + +.modal-header { + border: none!important; + padding: 15px 15px 0px 15px!important; +} + +.modal-header h3 { + font-family: "Open Sans"; + color: #191919; + font-size: 22px; + font-weight: 300; + line-height: 16px; + padding-bottom: 20px; + border-bottom: 3px solid #009fdb; + +} + +.control-label { + font-family: "Open Sans"; + color: #5a5a5a; + font-size: 13px; + font-weight: 400; +} + +.modal-footer { + background-color: #eaeaea; +} + +.modal-dialog { + width: 587px; + border-radius: 8px; +} + +.modal-content { + width: 587px; + border-radius: 8px; + background-color: #ffffff; +} + +button.dropdown-toggle { + text-align: left; +} + +button[disabled].dropdown-toggle { + opacity: 1; + cursor: not-allowed; + background-color: #eee; + border: 1px solid #aaa; + color: #a0a0a0; +} + +multiselect[disabled] { + cursor: not-allowed; +} + +a.item-unselected:before { + font-family: "icomoon"!important; + content: "\e90c"; + color: #4ca90c; +} + +.modal-close { + margin: -40px 5px 0 0; + color: #5a5a5a; + font-size: 20px; + cursor: pointer; +} + +.vnf-versions-container .table { + position: relative; + background-color: #f8f8f8; + background-clip: padding-box; + border-radius: 6px; + outline: 0; +} + +.vnf-versions-name { + padding-top: 6px; + font-family: "Open Sans"; + position: absolute; +} + +.vnf-versions-select-as-text { + font-family: "Open Sans"; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + border: none; + overflow:hidden; + background-color: #f8f8f8; + height: 31px; +} + +.vnf-files-select { + z-index: 999; + opacity: 0.0; + position: absolute; + width: 23%; + cursor: pointer; + height:100%; +} diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.html new file mode 100644 index 000000000..71c7eb331 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-change-management/new-change-management.html @@ -0,0 +1,68 @@ + + +
+ + +
diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.controller.js b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.controller.js new file mode 100644 index 000000000..c8f44c715 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.controller.js @@ -0,0 +1,455 @@ +(function () { + 'use strict'; + + appDS2.controller("newSchedulerController", ["$scope", "$uibModal", "$uibModalInstance", "AaiService", "SchedulerService", "_", + "$log", "changeManagement", "$timeout", "$interval", "$filter", "VIDCONFIGURATION", "changeManagementService", newSchedulerController]); + + function newSchedulerController($scope, $uibModal, $uibModalInstance, AaiService, SchedulerService, _, $log, changeManagement, $timeout, $interval, $filter, VIDCONFIGURATION, changeManagementService) { + var vm = this; + var pollpromise; + + var init = function () { + vm.scheduler = {}; + vm.schedulingInfo = {}; + var callbackData = extractChangeManagementCallbackDataStr(changeManagement); + vm.vnfObject = changeManagement; + vm.schedulerObj = { + domain: 'ChangeManagement', + scheduleId: '', + scheduleName: 'VnfUpgrade/DWF', + userId: '', + domainData: [{ + 'WorkflowName': vm.scheduler.policy, + 'CallbackUrl': 'http://127.0.0.1:8989/scheduler/v1/loopbacktest/vid', + 'CallbackData': callbackData + }], + + schedulingInfo: { + normalDurationInSeconds: '', + additionalDurationInSeconds: '', + concurrencyLimit: '', + policyId: '', + vnfDetails: [ + { + groupId: "", + node: [], + changeWindow: [{ + startTime: '', + endTime: '' + }] + + } + ] + }, + + } + vm.schedulerObj1 = { + "domain": "ChangeManagement", + "scheduleName": "VnfUpgrade/DWF", + "userId": "su7376", + "domainData": [ + { + "WorkflowName": "HEAT Stack Software Update for vNFs", + "CallbackUrl": "http://127.0.0.1:8989/scheduler/v1/loopbacktest/vid", + "CallbackData": "testing" + } + ], + "schedulingInfo": { + "normalDurationInSeconds": 60, + "additionalDurationInSeconds": 60, + "concurrencyLimit": 60, + "policyId": "SNIRO_CM_1707.Config_MS_Demo_TimeLimitAndVerticalTopology_zone_localTime.1.xml", + "vnfDetails": [ + { + "groupId": "group1", + "node": ["satmo415vbc", "satmo455vbc"], + "changeWindow": [ + { + "startTime": "2017-08-08T16:37:30.521Z", + "endTime": "2017-08-08T16:37:30.521Z" + } + ] + } + ] + } + }; + + + vm.format = 'yyyy/MM/dd'; + vm.todate = new Date(); + vm.checkboxSelection = 'false'; + vm.fromDate = ''; + vm.toDate = ''; + vm.timeSlots = []; + + vm.changeManagement = {}; + + vm.subscribers = []; + + AaiService.getSubscribers(function (response) { + vm.subscribers = response; + }); + + vm.serviceTypes = []; + AaiService.getServices(function (response) { + vm.serviceTypes = response.data.service; + }); + + changeManagementService.getWorkflows() + .then(function (response) { + vm.workflows = response.data; + }) + .catch(function (error) { + $log.error(error); + }); + + //TODO: Get the VNF names from backend dynamically + vm.vnfNames = []; + + //TODO: Get the VNF types from backend dynamically + vm.vnfTypes = []; + + AaiService.getLoggedInUserID(function (response) { + vm.userID = response.data; + }); + vm.policys = []; + + var policyName = JSON.stringify({ + policyName: "SNIRO_1710.*", + configAttributes: { + service: "PlacementOptimizationPolicy" + } + }); + SchedulerService.getPolicyInfo(policyName, function (response) { + vm.policys = response.data.entity; + }); + }; + + vm.radioSelections = function (test) { + if (vm.checkboxSelection == "true") { + vm.fromDate = ''; + vm.toDate = '' + } + } + vm.close = function () { + $uibModalInstance.close(); + }; + + + function convertToSecs(number) { + var totalSecs; + if (vm.selectedOption === 'hours') { + totalSecs = number * 3600; + + } + else if (vm.selectedOption === 'minutes') { + totalSecs = number * 60; + } else { + totalSecs = number; + } + return totalSecs; + } + + vm.submit = function () { + vm.schedulingInfo = { + scheduleId: vm.schedulerID, + approvalDateTime: '2017-08-08T16:37:30.521Z', + approvalUserId: "sy6266", + approvalStatus: 'Accepted', + approvalType: 'Tier 2' + }; + + var approvalObj = JSON.stringify(vm.schedulingInfo); + SchedulerService.getSubmitForapprovedTimeslots(approvalObj, function (response) { + if (response.status == 200) { + openConfirmationModal("Successfully Sent for Approval"); + } + + }); + }; + + vm.reject = function () { + vm.schedulingInfo = { + scheduleId: vm.schedulerID, + approvalDateTime: '2017-08-08T16:37:30.521Z', + approvalUserId: "sy6266", + approvalStatus: 'Rejected', + approvalType: 'Tier 2' + } + + var approvalObj = JSON.stringify(vm.schedulingInfo) + SchedulerService.getSubmitForapprovedTimeslots(approvalObj, function (response) { + if (response.status == 200) { + openConfirmationModal("Successfully sent for Rejection"); + } + + }); + }; + + vm.schedule = function (myForm) { + $scope.$watch('fromDate', validateDates(myForm)); + $scope.$watch('toDate', validateDates(myForm)); + if (myForm.$valid) { + sendSchedulerReq() + } + }; + + + function sendSchedulerReq() { + var changeWindow = [{ + startTime: '', + endTime: '' + }]; + vm.timeSlots = []; + var fromDate = $filter('date')(new Date(vm.fromDate), "yyyy-MM-ddTHH:mmZ", "UTC"); + var toDate = $filter('date')(new Date(vm.toDate), "yyyy-MM-ddTHH:mmZ", "UTC"); + + changeWindow[0].startTime = fromDate; + changeWindow[0].endTime = toDate; + vm.schedulerObj.userId = vm.userID; + vm.schedulerObj.domainData[0].WorkflowName = changeManagement.workflow; + vm.schedulerObj.schedulingInfo.normalDurationInSeconds = convertToSecs(vm.scheduler.duration); + vm.schedulerObj.schedulingInfo.additionalDurationInSeconds = convertToSecs(vm.scheduler.fallbackDuration); + vm.schedulerObj.schedulingInfo.concurrencyLimit = vm.scheduler.concurrency; + vm.schedulerObj.schedulingInfo.policyId = vm.scheduler.policy.policyName; + vm.schedulerObj.schedulingInfo['vnfDetails'][0].groupId = 'groupId'; + vm.schedulerObj.schedulingInfo['vnfDetails'][0].node = getVnfData(changeManagement.vnfNames); + + vm.schedulerObj.schedulingInfo['vnfDetails'][0].changeWindow = changeWindow; + if (vm.checkboxSelection == "true") { //When Scheduled now we remove the changeWindow + delete vm.schedulerObj.schedulingInfo['vnfDetails'][0].changeWindow; + } + vm.schedulerObj.schedulingInfo['vnfDetails'][0].changeWindow = changeWindow; + delete vm.schedulerObj.schedulingInfo['vnfDetails'][0].changeWindow; + + var requestScheduler = JSON.stringify(vm.schedulerObj); + console.log(requestScheduler); + SchedulerService.getStatusSchedulerId(requestScheduler, function (response) { + vm.schedulerID = response.data.uuid; + vm.isSpinnerVisible = true; + if (vm.schedulerID) { + var scheduledID = JSON.stringify({scheduleId: vm.schedulerID}); + seviceCallToGetTimeSlots(); + } + }); + } + + function seviceCallToGetTimeSlots() { + + SchedulerService.getTimeSotsForSchedulerId(vm.schedulerID, function (response) { + if (vm.checkboxSelection == "false") { + if (response.data.entity.schedule) { + var scheduleColl = JSON.parse(response.data.entity.schedule); + if (scheduleColl.length > 0) { + vm.timeSlots = scheduleColl; + vm.isSpinnerVisible = false; + hasvaluereturnd = false; + $scope.stopPoll(); + openConfirmationModal(response.data.entity.scheduleId + " Successfully Returned TimeSlots."); + } + + } + else { + if (vm.timeSlots.length == 0 && hasthresholdreached == false) { + var polltime = VIDCONFIGURATION.SCHEDULER_POLLING_INTERVAL_MSECS; + pollpromise = poll(polltime, function () { + if (vm.timeSlots.length == 0) { + hasvaluereturnd = true; + seviceCallToGetTimeSlots() + } + else { + hasvaluereturnd = false; + } + + }); + + } else { + openConfirmationModal("Timeout error.") + } + } + + } + else { + if (response.data.entity) { + vm.isSpinnerVisible = false; + openConfirmationModal(response.data.entity.scheduleId + " Successfully Ready for Schedule.") + } + } + + }); + + } + + function openConfirmationModal(jobInfo) { + var modalInstance = $uibModal.open({ + templateUrl: 'app/vid/scripts/modals/alert-new-scheduler/alert-new-scheduler.html', + controller: 'alertNewSchedulerController', + controllerAs: 'vm', + resolve: { + jobInfo: function () { + return jobInfo; + } + } + }); + } + + var hasvaluereturnd = true; // Flag to check + var hasthresholdreached = false; + var thresholdvalue = VIDCONFIGURATION.SCHEDULER_MAX_POLLS; // interval threshold value + + function poll(interval, callback) { + return $interval(function () { + if (hasvaluereturnd) { //check flag before start new call + callback(hasvaluereturnd); + } + + thresholdvalue = thresholdvalue - 1; //Decrease threshold value + if (thresholdvalue == 0) { + $scope.stopPoll(); // Stop $interval if it reaches to threshold + } + }, interval) + } + + +// stop interval. + $scope.stopPoll = function () { + $interval.cancel(pollpromise); + thresholdvalue = 0; //reset all flags. + hasvaluereturnd = false; + hasthresholdreached = true; + vm.isSpinnerVisible = false; + } + + function getVnfData(arrColl) { + var vnfcolletion = []; + + for (var i = 0; i < arrColl.length; i++) { + vnfcolletion.push(arrColl[i].name); + } + + return vnfcolletion + } + + function validateDates(form) { + if (vm.checkboxSelection == "false") { + + if (form.startDate.$error.invalidDate || form.endDate.$error.invalidDate) { + form.startDate.$setValidity("endBeforeStart", true); //already invalid (per validDate directive) + } else { + //depending on whether the user used the date picker or typed it, this will be different (text or date type). + //creating a new date object takes care of that. + var endDate = new Date(vm.toDate); + var startDate = new Date(vm.fromDate); + form.startDate.$setValidity("endBeforeStart", endDate >= startDate); + } + } + } + + + function extractChangeManagementCallbackDataStr(changeManagement) { + var result = {}; + + result.requestType = changeManagement.workflow; + result.requestDetails = []; + + _.forEach(changeManagement.vnfNames, function (vnf) { + + var data = { + vnfName: vnf.name, + vnfInstanceId: vnf.id, + modelInfo: { + modelType: 'vnf', + modelInvariantId: vnf.properties['model-invariant-id'], + modelVersionId: vnf.modelVersionId, + modelName: vnf.properties['vnf-name'], + modelVersion: vnf.version, + modelCustomizationName: vnf.properties['model-customization-name'], + modelCustomizationId: vnf.properties['model-customization-id'] + }, + cloudConfiguration: { + lcpCloudRegionId: vnf.availableVersions[0].cloudConfiguration.lcpCloudRegionId, + tenantId: vnf.availableVersions[0].cloudConfiguration.tenantId + }, + requestInfo: { + source: vnf.availableVersions[0].requestInfo.source, + suppressRollback: vnf.availableVersions[0].requestInfo.suppressRollback, + requestorId: vnf.availableVersions[0].requestInfo.requestorId + }, + relatedInstanceList: [], + requestParameters: { + usePreload: vnf.availableVersions[0].requestParameters.usePreload + } + }; + + var serviceInstanceId = ''; + _.forEach(vnf['service-instance-node'], function (instanceNode) { + if(instanceNode['node-type'] === 'service-instance'){ + serviceInstanceId = instanceNode.properties['service-instance-id']; + } + }); + + + _.forEach(vnf.availableVersions[0].relatedInstanceList, function (related) { + + var rel = related.relatedInstance; + + var relatedInstance = { + instanceId: serviceInstanceId, + modelInfo: { + modelType: rel.modelInfo.modelType, + modelInvariantId: rel.modelInfo.modelInvariantId, + modelVersionId: rel.modelInfo.modelVersionId, + modelName: rel.modelInfo.modelName, + modelVersion: rel.modelInfo.modelVersion, + modelCustomizationName: rel.modelInfo.modelCustomizationName, + modelCustomizationId: rel.modelInfo.modelCustomizationId + } + }; + + if (rel.vnfInstanceId) + relatedInstance.instanceId = rel.vnfInstanceId; + + data.relatedInstanceList.push({relatedInstance: relatedInstance}); + }); + + + result.requestDetails.push(data); + } + ); + + + // _.forEach(changeManagement.vnfNames, function (vnfName) { + // if (vnfName && vnfName.version) { + // if (vnfName.selectedFile) { + // vnfName.version.requestParameters.userParams = vnfName.selectedFile; + // } + // result.requestDetails.push(vnfName.version) + // } + // }); + + return JSON.stringify(result); + } + + init(); + }; + + appDS2.directive('validDate', function () { + return { + restrict: 'A', + require: 'ngModel', + link: function (scope, element, attrs, control) { + control.$parsers.push(function (viewValue) { + var newDate = model.$viewValue; + control.$setValidity("invalidDate", true); + if (typeof newDate === "object" || newDate == "") return newDate; // pass through if we clicked date from popup + if (!newDate.match(/^\d{1,2}\/\d{1,2}\/((\d{2})|(\d{4}))$/)) + control.$setValidity("invalidDate", false); + return viewValue; + }); + } + }; + }) + + +})(); + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.css new file mode 100644 index 000000000..8da5c55c5 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.css @@ -0,0 +1,145 @@ +.btn-white { + font-family: OpenSans; + border-radius: 2px; + border: 1px solid #d8d8d8; + background-color: #ffffff; + width: 94px; + height: 30px; + color: #5a5a5a; + font-size: 13px; + font-weight: 400; + line-height: 36px; + text-align: center; +} + +.btn-primary { + font-family: OpenSans; + border-radius: 2px; + border: 1px solid #0091c8; + background-color: #009fdb; + width: 94px; + height: 30px; + color: #ffffff; + font-size: 13px; + font-weight: 400; + line-height: 36px; + text-align: center; +} + +.modal-header { + border: none!important; + padding: 15px 15px 0px 15px!important; +} + +.modal-header h3 { + font-family: OpenSans; + color: #5a5a5a; + font-size: 22px; + font-weight: 300; + line-height: 16px; + padding-bottom: 20px; + border-bottom: 3px solid #009fdb; + +} + +.modal-footer { + background-color: #eaeaea; +} + +.modal-dialog { + width: 587px; + border-radius: 8px; +} + +.modal-content { + width: 587px; + border-radius: 8px; + background-color: #ffffff; +} +.label-font{ + font-size: 1em; +} +.calender-icon{ + background-image: url(../../../../../app/fusion/external/ebz/images/Calendar.svg); + background-repeat:no-repeat; + background-position:98%; + border-radius: 6px; + border: 1px solid #888; + color: #444; + font-family: clearview_att_regular; + width: 100%; + outline: 0; + padding: 7px 10px; + text-transform: none; + z-index: 0; + height: 40px; + position: relative; + +} + +input.calender-icon:focus{ + background-image: url(../../../../../app/fusion/external/ebz/images/Calendar_blue.svg); + background-repeat:no-repeat; +} + + + +.timeslots-content{ + margin-top: 0px; + margin-bottom: 0px; + height: 10em; +} +.find-block{ + float:5em; +} +.timeslots-block{ +/* margin-top: 1em; */ + height: 85px; + } + .policy-combo{ + background-image: none; + } + + div[ng-controller=newSchedulerController] .schedulerVisible { + visibility: visible; +} +div[ng-controller=newSchedulerController] .schedulerHidden { + visibility: hidden; +} + +.table { + border: 1px solid #eaeaea; + box-sizing: border-box; + background-color: #ffffff; + box-shadow: 0px 2px 7px 0px rgba(34, 31, 31, 0.17); + font-family: OpenSans; + color: #5a5a5a; + font-size: 14px; + font-weight: 400; +} +.table>thead { + background-color: #d2d2d2; + font-family: OpenSans; + color: #191919; + font-size: 13px; + font-weight: 600; + line-height: 40px; +} + +.table-headline-row { + font-family: OpenSans; + color: #5a5a5a; + font-size: 14px; + font-weight: 600; + background-color: #eaeaea; + box-shadow: 0px 1px 1px 0px rgba(34, 31, 31, 0.19); +} + +.table-bordered{border:1px solid #eaeaea;} +.table-bordered>tbody>tr>td, +.table-bordered>tbody>tr>th, +.table-bordered>tfoot>tr>td, +.table-bordered>tfoot>tr>th, +.table-bordered>thead>tr>td, +.table-bordered>thead>tr>th{border:1px solid #eaeaea;} + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.html new file mode 100644 index 000000000..498ff2ec4 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/new-scheduler/new-scheduler.html @@ -0,0 +1,101 @@ + + +
+ + +
+ diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.css b/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.css new file mode 100644 index 000000000..d545a5cdc --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.css @@ -0,0 +1,7 @@ +.modal-header h3 { + border-bottom: 3px solid #00aeef; +} + +.btn-primary { + padding: 4px 9px !important; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.html new file mode 100644 index 000000000..911e86c24 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/modals/pending-change-management/pending-change-management.html @@ -0,0 +1,12 @@ + + + + + diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/services/aaiService.js b/vid-app-common/src/main/webapp/app/vid/scripts/services/aaiService.js index 09c70eb5b..a10f602bf 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/services/aaiService.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/services/aaiService.js @@ -20,9 +20,9 @@ "use strict"; -var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONENT, FIELD) { +var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONENT, FIELD, $q) { return { - getSubscriberName: function (globalCustomerId, + getSubscriberName : function(globalCustomerId, successCallbackFunction) { $log .debug("AaiService:getSubscriberName: globalCustomerId: " @@ -31,9 +31,9 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE COMPONENT.AAI_SUB_DETAILS_PATH + globalCustomerId + COMPONENT.ASSIGN + Math.random(), { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { var subName = ""; if (response.data) { subName = response.data[FIELD.ID.SUBNAME]; @@ -44,7 +44,7 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE }, - runNamedQuery: function (namedQueryId, globalCustomerId, serviceType, serviceInstanceId, successCallback, errorCallback) { + runNamedQuery : function (namedQueryId, globalCustomerId, serviceType, serviceInstanceId, successCallback, errorCallback) { var url = COMPONENT.AAI_SUB_VIEWEDIT_PATH + COMPONENT.FORWARD_SLASH + encodeURIComponent(namedQueryId) + @@ -52,30 +52,54 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE COMPONENT.FORWARD_SLASH + encodeURIComponent(serviceType) + COMPONENT.FORWARD_SLASH + encodeURIComponent(serviceInstanceId); $http.get(url, {}, { - timeout: PropertyService.getServerResponseTimeoutMsec() - }).then(function (response) { + + + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(function(response) { if (response.data != null) { successCallback(response); } else { errorCallback(response); } - }, function (response) { + }, function(response) { errorCallback(response); }); }, - getSubDetails: function (selectedSubscriber, selectedServiceInstance, successCallback, errorCallback) { + getVNFInformationByServiceTypeAndId : function (globalCustomerId, serviceType, serviceInstanceId, successCallback, errorCallback) { + + var url = COMPONENT.AAI_GET_VNF_INFO + + COMPONENT.FORWARD_SLASH + encodeURIComponent(globalCustomerId) + + COMPONENT.FORWARD_SLASH + encodeURIComponent(serviceType) + + COMPONENT.FORWARD_SLASH + encodeURIComponent(serviceInstanceId); + $http.get(url, {}, { + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data != null) { + successCallback(response); + } else { + errorCallback(response); + } + }, function(response) { + errorCallback(response); + }); + }, + + + getSubDetails : function(selectedSubscriber, selectedServiceInstance, successCallback, errorCallback) { var subscriber; var displayData; - $http.get(COMPONENT.AAI_SUB_DETAILS_PATH + selectedSubscriber, {}, { - timeout: PropertyService.getServerResponseTimeoutMsec() - }).then(function (response) { + $http.get( COMPONENT.AAI_SUB_DETAILS_PATH + selectedSubscriber, {}, { + + + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(function(response) { displayData = []; subscriber = response.data; var subscriberName = subscriber[FIELD.ID.SUBNAME]; if (subscriber[FIELD.ID.SERVICE_SUBSCRIPTIONS] != null) { - angular.forEach(subscriber[FIELD.ID.SERVICE_SUBSCRIPTIONS][FIELD.ID.SERVICE_SUBSCRIPTION], function (serviceSubscription, key) { + angular.forEach(subscriber[FIELD.ID.SERVICE_SUBSCRIPTIONS][FIELD.ID.SERVICE_SUBSCRIPTION], function(serviceSubscription, key) { var serviceInstanceId = []; var serviceType = ""; if (serviceSubscription[FIELD.ID.SERVICETYPE] != null) { @@ -84,10 +108,9 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE serviceType = FIELD.PROMPT.NO_SERVICE_SUB; } if (serviceSubscription[FIELD.ID.SERVICE_INSTANCES] != null) { - angular.forEach(serviceSubscription[FIELD.ID.SERVICE_INSTANCES][FIELD.ID.SERVICE_INSTANCE], function (instValue, instKey) { + angular.forEach(serviceSubscription[FIELD.ID.SERVICE_INSTANCES][FIELD.ID.SERVICE_INSTANCE], function(instValue, instKey) { // put them together, i guess - var inst = { - "serviceInstanceId": instValue[FIELD.ID.SERVICE_INSTANCE_ID], + var inst = { "serviceInstanceId": instValue[FIELD.ID.SERVICE_INSTANCE_ID], "aaiModelInvariantId": instValue[FIELD.ID.MODEL_INVAR_ID], "aaiModelVersionId": instValue[FIELD.ID.MODEL_VERSION_ID], "serviceInstanceName": instValue[FIELD.ID.SERVICE_INSTANCE_NAME] @@ -102,111 +125,109 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE }); } else { if (serviceInstanceId == []) { - serviceInstanceId = [FIELD.PROMPT.NO_SERVICE_INSTANCE]; + serviceInstanceId = [ FIELD.PROMPT.NO_SERVICE_INSTANCE ]; } } - angular.forEach(serviceInstanceId, function (subVal, subKey) { + angular.forEach(serviceInstanceId, function(subVal, subKey) { displayData.push({ - globalCustomerId: selectedSubscriber, - subscriberName: subscriberName, - serviceType: serviceType, - serviceInstanceId: subVal.serviceInstanceId, - aaiModelInvariantId: subVal.aaiModelInvariantId, - aaiModelVersionId: subVal.aaiModelVersionId, - serviceInstanceName: subVal.serviceInstanceName, + globalCustomerId : selectedSubscriber, + subscriberName : subscriberName, + serviceType : serviceType, + serviceInstanceId : subVal.serviceInstanceId, + aaiModelInvariantId : subVal.aaiModelInvariantId, + aaiModelVersionId + : subVal.aaiModelVersionId, + serviceInstanceName : subVal.serviceInstanceName, isPermitted: serviceSubscription[FIELD.ID.IS_PERMITTED] }); }); }); } else { displayData.push({ - globalCustomerId: selectedSubscriber, - subscriberName: selectedSubscriberName, - serviceType: FIELD.PROMPT.NO_SERVICE_SUB, - serviceInstanceId: FIELD.PROMPT.NO_SERVICE_INSTANCE + globalCustomerId : selectedSubscriber, + subscriberName : selectedSubscriberName, + serviceType : FIELD.PROMPT.NO_SERVICE_SUB, + serviceInstanceId : FIELD.PROMPT.NO_SERVICE_INSTANCE }); } successCallback(displayData, subscriberName); - }, function (response) { - errorCallback(response); - }); + }, function(response) { + errorCallback(response);}); }, - getSubList: function (successCallback, errorCallback) { - $http.get(FIELD.ID.AAI_GET_FULL_SUBSCRIBERS, {}, { - timeout: PropertyService.getServerResponseTimeoutMsec() - }).then(function (response) { + getSubList : function(successCallback, errorCallback ) { + + $http.get( FIELD.ID.AAI_GET_FULL_SUBSCRIBERS, {}, { + + + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(function(response) { var customerList = []; if (response.data.customer != null) { - angular.forEach(response.data.customer, function (subVal, subKey) { - var cust = { - "globalCustomerId": subVal[FIELD.ID.GLOBAL_CUSTOMER_ID], - "subscriberName": subVal[FIELD.ID.SUBNAME], - "isPermitted": subVal[FIELD.ID.IS_PERMITTED], - }; + angular.forEach(response.data.customer, function(subVal, subKey) { + var cust = { "globalCustomerId": subVal[FIELD.ID.GLOBAL_CUSTOMER_ID], "subscriberName": subVal[FIELD.ID.SUBNAME], + "isPermitted": subVal[FIELD.ID.IS_PERMITTED], }; customerList.push(cust); }); successCallback(customerList); } else { errorCallback(response); } - }, function (response) { + },function(response) { errorCallback(response); }); }, - getServices2: function (successCallback, errorCallback) { + getServices2 : function(successCallback, errorCallback ) { - $http.get(FIELD.ID.AAI_GET_SERVICES, {}, { - timeout: PropertyService.getServerResponseTimeoutMsec() - }).then(function (response) { + $http.get( FIELD.ID.AAI_GET_SERVICES, {}, { + + + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(function(response) { var customerList = []; if (response.data != null) { var serviceIdList = []; - angular.forEach(response.data, function (value, key) { - angular.forEach(value, function (subVal, key) { - var newVal = { - "id": subVal[FIELD.ID.SERVICE_ID], - "description": subVal[FIELD.ID.SERVICE_DESCRIPTION], + angular.forEach(response.data, function(value, key) { + angular.forEach(value, function(subVal, key) { + var newVal = { "id" : subVal[FIELD.ID.SERVICE_ID], "description" : subVal[FIELD.ID.SERVICE_DESCRIPTION] , "isPermitted" : subVal[FIELD.ID.IS_PERMITTED] - }; - serviceIdList.push(newVal); + };serviceIdList.push(newVal); }); }); successCallback(serviceIdList); } else { errorCallback(response); } - }, function (response) { + },function(response) { errorCallback(response); }); }, - getSubscriptionServiceTypeList: function (globalCustomerId, + getSubscriptionServiceTypeList : function(globalCustomerId, successCallbackFunction) { $log .debug("AaiService:getSubscriptionServiceTypeList: globalCustomerId: " + globalCustomerId); - if (UtilityService.hasContents(globalCustomerId)) { + if ( UtilityService.hasContents(globalCustomerId) ) { $http.get( COMPONENT.AAI_SUB_DETAILS_PATH + globalCustomerId + COMPONENT.ASSIGN + Math.random(), { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data && response.data[FIELD.ID.SERVICE_SUBSCRIPTIONS]) { var serviceTypes = []; var serviceSubscriptions = response.data[FIELD.ID.SERVICE_SUBSCRIPTIONS][FIELD.ID.SERVICE_SUBSCRIPTION]; for (var i = 0; i < serviceSubscriptions.length; i++) { serviceTypes.push({ - "name": serviceSubscriptions[i][FIELD.ID.SERVICETYPE], + "name":serviceSubscriptions[i][FIELD.ID.SERVICETYPE], "isPermitted": serviceSubscriptions[i][FIELD.ID.IS_PERMITTED], "id": i - }); - } + });} successCallbackFunction(serviceTypes); } else { successCallbackFunction([]); @@ -215,19 +236,19 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE (UtilityService.runHttpErrorHandler); } }, - getLcpCloudRegionTenantList: function (globalCustomerId, serviceType, + getLcpCloudRegionTenantList : function(globalCustomerId, serviceType, successCallbackFunction) { $log .debug("AaiService:getLcpCloudRegionTenantList: globalCustomerId: " + globalCustomerId); - var url = COMPONENT.AAI_GET_TENANTS + var url = COMPONENT.AAI_GET_TENANTS + globalCustomerId + COMPONENT.FORWARD_SLASH + serviceType + COMPONENT.ASSIGN + Math.random(); $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { var lcpCloudRegionTenants = []; var aaiLcpCloudRegionTenants = response.data; @@ -242,24 +263,23 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE "cloudRegionId": aaiLcpCloudRegionTenants[i][COMPONENT.CLOUD_REGION_ID], "tenantName": aaiLcpCloudRegionTenants[i][COMPONENT.TENANT_NAME], "tenantId": aaiLcpCloudRegionTenants[i][COMPONENT.TENANT_ID], - "isPermitted": aaiLcpCloudRegionTenants[i][COMPONENT.IS_PERMITTED] - }); + "isPermitted": aaiLcpCloudRegionTenants[i][COMPONENT.IS_PERMITTED]}); } successCallbackFunction(lcpCloudRegionTenants); })["catch"] (UtilityService.runHttpErrorHandler); }, - getSubscribers: function (successCallbackFunction) { + getSubscribers : function(successCallbackFunction) { $log .debug("AaiService:getSubscribers"); - var url = FIELD.ID.AAI_GET_SUBSCRIBERS + COMPONENT.ASSIGN + Math.random(); + var url = FIELD.ID.AAI_GET_SUBSCRIBERS + COMPONENT.ASSIGN + Math.random(); $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response.data.customer); } else { @@ -268,16 +288,16 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE })["catch"] (UtilityService.runHttpErrorHandler); }, - getProvOptionsFromSystemProp: function (successCallbackFunction) { + getProvOptionsFromSystemProp : function(successCallbackFunction) { $log .debug("AaiService:getProvOptionsFromSystemProp"); - var url = COMPONENT.GET_SYSTEM_PROP_VNF_PROV_STATUS_PATH; + var url = COMPONENT.GET_SYSTEM_PROP_VNF_PROV_STATUS_PATH; $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response); } else { @@ -286,28 +306,31 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE })["catch"] (UtilityService.runHttpErrorHandler); }, - getLoggedInUserID: function (successCallbackFunction) { + getLoggedInUserID : function(successCallbackFunction) { $log .debug("AaiService:getLoggedInUserID"); var url = COMPONENT.GET_USER_ID; $http.get(url, { - timeout: PropertyService + transformResponse: [function (data) { + return data; + }], + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response); } else { successCallbackFunction([]); } - })["catch"] + },function(failure){console.log("failure")})["catch"] (UtilityService.runHttpErrorHandler); }, - getServices: function (successCallbackFunction) { + getServices : function(successCallbackFunction) { $log .debug("AaiService:getServices"); - var url = COMPONENT.AAI_GET_SERVICES + COMPONENT.ASSIGN + Math.random(); + var url = COMPONENT.AAI_GET_SERVICES + COMPONENT.ASSIGN + Math.random(); $http.get(url, { @@ -326,31 +349,46 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE getAicZones: function (successCallbackFunction) { $log .debug("getAicZones:getAicZones"); - var url = COMPONENT.AAI_GET_AIC_ZONES + COMPONENT.ASSIGN + Math.random(); + var url = COMPONENT.AAI_GET_AIC_ZONES +COMPONENT.ASSIGN + Math.random(); $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response); } else { successCallbackFunction([]); } })["catch"] - (UtilityService.runHttpErrorHandler); - }, - getServiceModels: function (globalCustomerId, serviceType, successCallbackFunction) { + (UtilityService.runHttpErrorHandler);}, + getAicZoneForPNF: function (globalCustomerId,serviceType,serviceInstanceId,successCallbackFunction) { + $log + .debug("getAicZones:getAicZones"); + var url = COMPONENT.AAI_GET_AIC_ZONE_FOR_PNF + .replace('@serviceInstanceId', serviceInstanceId) + .replace('@globalCustomerId', globalCustomerId) + .replace('@serviceType', serviceType); + $http.get(url, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + successCallbackFunction(response.data); + })["catch"] + (UtilityService.runHttpErrorHandler);}, + + getServiceModels : function(globalCustomerId,serviceType,successCallbackFunction) { $log .debug("AaiService:getServices"); - var url = COMPONENT.AAI_GET_SERVICES + COMPONENT.FORWARD_SLASH + globalCustomerId + COMPONENT.FORWARD_SLASH + serviceType + COMPONENT.ASSIGN + Math.random(); + var url = COMPONENT.AAI_GET_SERVICES + COMPONENT.FORWARD_SLASH+globalCustomerId+ COMPONENT.FORWARD_SLASH +serviceType+COMPONENT.ASSIGN + Math.random(); $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response); } else { @@ -359,16 +397,16 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE })["catch"] (UtilityService.runHttpErrorHandler); }, - getServiceModelsByServiceType: function (namedQueryId, globalCustomerId, serviceType, successCallbackFunction) { + getServiceModelsByServiceType : function(namedQueryId,globalCustomerId,serviceType,successCallbackFunction) { $log .debug("AaiService:getServiceModelsByServiceType"); - var url = COMPONENT.AAI_GET_SERVICES_BY_TYPE + COMPONENT.FORWARD_SLASH + namedQueryId + COMPONENT.FORWARD_SLASH + globalCustomerId + COMPONENT.FORWARD_SLASH + serviceType + COMPONENT.ASSIGN + Math.random(); + var url = COMPONENT.AAI_GET_SERVICES_BY_TYPE+COMPONENT.FORWARD_SLASH+namedQueryId+COMPONENT.FORWARD_SLASH+globalCustomerId+COMPONENT.FORWARD_SLASH +serviceType+COMPONENT.ASSIGN + Math.random(); $http.get(url, { - timeout: PropertyService + timeout : PropertyService .getServerResponseTimeoutMsec() - }).then(function (response) { + }).then(function(response) { if (response.data) { successCallbackFunction(response); } else { @@ -376,9 +414,71 @@ var AaiService = function ($http, $log, PropertyService, UtilityService, COMPONE } })["catch"] (UtilityService.runHttpErrorHandler); + }, + + getVnfsByCustomerIdAndServiceType: function(globalSubscriberId, serviceType){ + var deferred = $q.defer(); + + if (UtilityService.hasContents(globalSubscriberId) && + UtilityService.hasContents(serviceType) ) { + + $http.get(COMPONENT.AAI_GET_VNF_BY_CUSTOMERID_AND_SERVICETYPE + globalSubscriberId + COMPONENT.FORWARD_SLASH + + serviceType ) + .success(function (response) { + if(response) { + deferred.resolve({data: response}); + } else { + deferred.resolve({data: []}); + } + }).error(function (data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + } + + return deferred.promise; + }, + + getVnfVersionsByInvariantId: function(modelInvariantId){ + var deferred = $q.defer(); + + if (UtilityService.hasContents(modelInvariantId)) { + var body = {"versions" : modelInvariantId} + $http.post(( COMPONENT.AAI_GET_VERSION_BY_INVARIANT_ID),body) + + .success(function (response) { + if(response) { + deferred.resolve({data: response}); + } else { + deferred.resolve({data: []}); + } + }).error(function (data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + } + + return deferred.promise; + }, + + getSubscriberServiceTypes: function(subscriberUuid) { + var deferred = $q.defer(); + $log.debug("AaiService:getSubscriberServiceTypes: subscriberUuid: " + subscriberUuid); + + if (UtilityService.hasContents(subscriberUuid)) { + $http.get(COMPONENT.AAI_SUB_DETAILS_PATH + subscriberUuid + COMPONENT.ASSIGN + Math.random()) + .success(function (response) { + if(response && [FIELD.ID.SERVICE_SUBSCRIPTIONS]) { + deferred.resolve({data: response[FIELD.ID.SERVICE_SUBSCRIPTIONS][FIELD.ID.SERVICE_SUBSCRIPTION]}); + } else { + deferred.resolve({data: []}); + } + }).error(function (data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + } + + return deferred.promise; } - } -} + }}; appDS2.factory("AaiService", ["$http", "$log", "PropertyService", - "UtilityService", "COMPONENT", "FIELD", AaiService]); + "UtilityService", "COMPONENT", "FIELD", "$q", AaiService]); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/services/change-management.service.js b/vid-app-common/src/main/webapp/app/vid/scripts/services/change-management.service.js new file mode 100644 index 000000000..f2282d69a --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/services/change-management.service.js @@ -0,0 +1,76 @@ +(function () { + 'use strict'; + + appDS2.service('changeManagementService', ['$http', '$q', 'COMPONENT', 'VIDCONFIGURATION', changeManagementService]); + + function changeManagementService($http, $q, COMPONENT, VIDCONFIGURATION) { + this.getWorkflows = function (vnfs) { + var deferred = $q.defer(); + + $http.get(COMPONENT.GET_WORKFLOW.replace("@vnfs", vnfs)) + .success(function (response) { + deferred.resolve({data: response}); + }).error(function (data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + + return deferred.promise; + }; + + this.getMSOChangeManagements = function() { + var deferred = $q.defer(); + + $http.get(COMPONENT.GET_MSO_WORKFLOWS) + .success(function (response) { + deferred.resolve({data: response}); + }) + .error(function(data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + + return deferred.promise; + }; + + this.getAllSDCServices = function () { + var deferred = $q.defer(); + + $http.get(COMPONENT.SERVICES_DIST_STATUS_PATH + VIDCONFIGURATION.ASDC_MODEL_STATUS) + .success(function (response) { + deferred.resolve({data: response}); + }) + .error(function(data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + + return deferred.promise; + }; + + this.getSDCService = function(uuid) { + var deferred = $q.defer(); + + $http.get(COMPONENT.SERVICES_PATH + uuid) + .success(function (response) { + deferred.resolve({data: response}); + }) + .error(function(data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + + return deferred.promise; + }; + + this.getSchedulerChangeManagements = function(){ + var deferred = $q.defer(); + + $http.get(COMPONENT.GET_SCHEDULER_CHANGE_MANAGEMENTS) + .success(function (response) { + deferred.resolve({data: response}); + }) + .error(function(data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + + return deferred.promise; + }; + } +})(); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/services/creationService.js b/vid-app-common/src/main/webapp/app/vid/scripts/services/creationService.js index 9309ce6cc..e171e2856 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/services/creationService.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/services/creationService.js @@ -274,7 +274,6 @@ var CreationService = function($log, AaiService, AsdcService, DataService,VIDCON } parameterList.push(FIELD.PARAMETER.SUPPRESS_ROLLBACK); if(_this.componentId === COMPONENT.VF_MODULE ){ - if(DataService.getSubscriberName() === FIELD.NAME.MOBILITY){ parameterList.push({name: FIELD.NAME.SDN_C_PRELOAD, id: FIELD.ID.SDN_C_PRELOAD, type: "checkbox", @@ -283,7 +282,6 @@ var CreationService = function($log, AaiService, AsdcService, DataService,VIDCON hideFieldAndLabel: true } ); - } parameterList.push({name: FIELD.NAME.UPLOAD_SUPPLEMENTORY_DATA_FILE, id: FIELD.ID.UPLOAD_SUPPLEMENTORY_DATA_FILE, type: "checkbox", @@ -602,7 +600,7 @@ var CreationService = function($log, AaiService, AsdcService, DataService,VIDCON requestDetails.requestParameters.usePreload = getValueFromList( FIELD.ID.SDN_C_PRELOAD, parameterList); if(_this.componentId == COMPONENT.VF_MODULE &&(requestDetails.requestParameters.usePreload== null || requestDetails.requestParameters.usePreload === '')){ - requestDetails.requestParameters.usePreload = true; + requestDetails.requestParameters.usePreload = false; } break; case COMPONENT.VOLUME_GROUP: diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/services/msoService.js b/vid-app-common/src/main/webapp/app/vid/scripts/services/msoService.js index 864abe67d..68c8503dc 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/services/msoService.js +++ b/vid-app-common/src/main/webapp/app/vid/scripts/services/msoService.js @@ -20,156 +20,240 @@ "use strict"; -var MsoService = function($http, $log, PropertyService, UtilityService, COMPONENT, FIELD) { +var MsoService = function($http, $log, PropertyService, AaiService, UtilityService, COMPONENT, FIELD, $q) { - var _this = this; + var _this = this; /* * Common function to handle both create and delete instance requests */ - var requestInstanceUpdate = function(request, successCallbackFunction) { - $log.debug("MsoService:requestInstanceUpdate: request:"); - $log.debug(request); - $http.post( "mso/" + request.url, { - requestDetails : request.requestDetails - }, { - timeout : PropertyService.getServerResponseTimeoutMsec() - }).then(successCallbackFunction)["catch"] - (UtilityService.runHttpErrorHandler); - } - - var checkValidStatus = function(response) { - if (response.data.status < 200 || response.data.status > 202) { - throw { - type : FIELD.ID.MSO_FAILURE - } - } - } - - var addListEntry = function(name, value) { - var entry = '"' + name + '": '; - if (value === undefined) { - return entry + "undefined"; - } else { - return entry + '"' + value + '"'; - } - } - - return { - createInstance : requestInstanceUpdate, - deleteInstance : requestInstanceUpdate, - getOrchestrationRequest : function(requestId, successCallbackFunction) { - $log.debug("MsoService:getOrchestrationRequest: requestId: " - + requestId); - $http.get( - "mso/mso_get_orch_req/" - + requestId + "?r=" + Math.random(), - { - timeout : PropertyService - .getServerResponseTimeoutMsec() - }).then(successCallbackFunction)["catch"] - (UtilityService.runHttpErrorHandler); - }, - getOrchestrationRequests : function(filterString, - successCallbackFunction) { - $log.debug("MsoService:getOrchestrationRequests: filterString: " - + filterString); - $http.get( - "mso/mso_get_orch_reqs/" - + encodeURIComponent(filterString) + "?r=" - + Math.random(), - { - timeout : PropertyService - .getServerResponseTimeoutMsec() - }).then(successCallbackFunction)["catch"] - (UtilityService.runHttpErrorHandler); - }, - getFormattedCommonResponse : function(response) { - return UtilityService.getCurrentTime() + " HTTP Status: " - + UtilityService.getHttpStatusText(response.data.status) - + "\n" + angular.toJson(response.data.entity, true) - - }, - checkValidStatus : checkValidStatus, - getFormattedGetOrchestrationRequestsResponse : function(response) { - UtilityService.checkUndefined(COMPONENT.ENTITY, response.data.entity); - UtilityService.checkUndefined(COMPONENT.STATUS, response.data.status); - checkValidStatus(response); - - var list = response.data.entity.requestList - UtilityService.checkUndefined(FIELD.ID.REQUEST_LIST, list); - - var message = ""; - - for (var i = 0; i < list.length; i++) { - var request = list[i].request; - message += addListEntry(FIELD.ID.REQUEST_ID, request.requestId) + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_TYPE, request.requestType) - + ",\n"; - var status = request.requestStatus; - if (status === undefined) { - message += addListEntry(FIELD.ID.REQUEST_STATUS, undefined) + "\n"; - } else { - message += addListEntry(FIELD.ID.TIMESTAMP, status.timestamp) - + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_STATE, status.requestState) - + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_STATUS, - status.statusMessage) - + ",\n"; - message += addListEntry(FIELD.ID.PERCENT_PROGRESS, - status.percentProgress) - + "\n"; - } - if (i < (list.length - 1)) { - message += "\n"; - } - } - return message; - }, - getFormattedSingleGetOrchestrationRequestResponse : function (response) { - UtilityService.checkUndefined(COMPONENT.ENTITY, response.data.entity); - UtilityService.checkUndefined(COMPONENT.STATUS, response.data.status); - checkValidStatus(response); - - var message = ""; - if ( UtilityService.hasContents (response.data.entity.request) ) { - var request = response.data.entity.request; - message += addListEntry(FIELD.ID.REQUEST_ID, request.requestId) + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_TYPE, request.requestType) - + ",\n"; - var status = request.requestStatus; - if (status === undefined) { - message += addListEntry(FIELD.ID.REQUEST_STATUS, undefined) + "\n"; - } else { - message += addListEntry(FIELD.ID.TIMESTAMP, status.timestamp) - + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_STATE, status.requestState) - + ",\n"; - message += addListEntry(FIELD.ID.REQUEST_STATUS, - status.statusMessage) - + ",\n"; - message += addListEntry(FIELD.ID.PERCENT_PROGRESS, - status.percentProgress) - + "\n\n"; - } - } - return message; - }, - showResponseContentError : function(error, showFunction) { - switch (error.type) { - case "undefinedObject": - showFunction(FIELD.ERROR.SYSTEM_FAILURE, error.message); - break; - case "msoFailure": - showFunction(FIELD.ERROR.MSO, "") - break; - default: - showFunction(FIELD.ERROR.SYSTEM_FAILURE); - } - } - } -} + var requestInstanceUpdate = function(request, successCallbackFunction) { + $log.debug("MsoService:requestInstanceUpdate: request:"); + $log.debug(request); + $http.post( "mso/" + request.url, { + requestDetails : request.requestDetails + }, { + timeout : PropertyService.getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + } + + var checkValidStatus = function(response) { + if (response.data.status < 200 || response.data.status > 202) { + throw { + type : FIELD.ID.MSO_FAILURE + } + } + }; + + var addListEntry = function(name, value) { + var entry = '"' + name + '": '; + if (value === undefined) { + return entry + "undefined"; + } else { + return entry + '"' + value + '"'; + } + }; + + var activateInstance = function(instance, model) { + var deferred = $q.defer(); + + AaiService.getLoggedInUserID(function (response) { + var userID = response.data; + + AaiService.getAicZoneForPNF(instance.globalCustomerId, model.service.serviceType, instance.serviceInstanceId, function (aicZone) { + + var requestDetails = { + "modelInstanceId": serviceInstanceId, + "requestDetails": { + "modelInfo": { + "modelType": "service", + "modelInvariantId": model.service.invariantUuid, + "modelVersionId": model.service.uuid, + "modelName": model.service.name, + "modelVersion": model.service.version + }, + "requestInfo": { + "source": "VID", + "requestorId": userID + }, + "requestParameters": { + "userParams": { + "name": "aic_zone", + "value": aicZone + } + } + } + }; + + console.log("requestDetails", requestDetails); + + $http.post(COMPONENT.MSO_ACTIVATE_INSTANCE.replace('@serviceInstanceId', requestDetails.modelInstanceId), + requestDetails.requestDetails) + .success(function (response) { + deferred.resolve({data: response}); + }) + .error(function(data, status, headers, config) { + deferred.reject({message: data, status: status}); + }); + }); + }); + + return deferred.promise; + }; + + return { + createInstance : requestInstanceUpdate, + deleteInstance : requestInstanceUpdate, + getOrchestrationRequest : function(requestId, successCallbackFunction) { + $log.debug("MsoService:getOrchestrationRequest: requestId: " + + requestId); + $http.get( + "mso/mso_get_orch_req/" + + requestId + "?r=" + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + }, + getOrchestrationRequests : function(filterString, + successCallbackFunction) { + $log.debug("MsoService:getOrchestrationRequests: filterString: " + + filterString); + $http.get( + "mso/mso_get_orch_reqs/" + + encodeURIComponent(filterString) + "?r=" + + Math.random(), + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(successCallbackFunction)["catch"] + (UtilityService.runHttpErrorHandler); + }, + getFormattedCommonResponse : function(response) { + return UtilityService.getCurrentTime() + " HTTP Status: " + + UtilityService.getHttpStatusText(response.data.status) + + "\n" + angular.toJson(response.data.entity, true) + + }, + checkValidStatus : checkValidStatus, + getFormattedGetOrchestrationRequestsResponse : function(response) { + UtilityService.checkUndefined(COMPONENT.ENTITY, response.data.entity); + UtilityService.checkUndefined(COMPONENT.STATUS, response.data.status); + checkValidStatus(response); + + var list = response.data.entity.requestList + UtilityService.checkUndefined(FIELD.ID.REQUEST_LIST, list); + + var message = ""; + + for (var i = 0; i < list.length; i++) { + var request = list[i].request; + message += addListEntry(FIELD.ID.REQUEST_ID, request.requestId) + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_TYPE, request.requestType) + + ",\n"; + var status = request.requestStatus; + if (status === undefined) { + message += addListEntry(FIELD.ID.REQUEST_STATUS, undefined) + "\n"; + } else { + message += addListEntry(FIELD.ID.TIMESTAMP, status.timestamp) + + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_STATE, status.requestState) + + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_STATUS, + status.statusMessage) + + ",\n"; + message += addListEntry(FIELD.ID.PERCENT_PROGRESS, + status.percentProgress) + + "\n"; + } + if (i < (list.length - 1)) { + message += "\n"; + } + } + return message; + }, + getFormattedSingleGetOrchestrationRequestResponse : function (response) { + UtilityService.checkUndefined(COMPONENT.ENTITY, response.data.entity); + UtilityService.checkUndefined(COMPONENT.STATUS, response.data.status); + checkValidStatus(response); + + var message = ""; + if ( UtilityService.hasContents (response.data.entity.request) ) { + var request = response.data.entity.request; + message += addListEntry(FIELD.ID.REQUEST_ID, request.requestId) + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_TYPE, request.requestType) + + ",\n"; + var status = request.requestStatus; + if (status === undefined) { + message += addListEntry(FIELD.ID.REQUEST_STATUS, undefined) + "\n"; + } else { + message += addListEntry(FIELD.ID.TIMESTAMP, status.timestamp) + + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_STATE, status.requestState) + + ",\n"; + message += addListEntry(FIELD.ID.REQUEST_STATUS, + status.statusMessage) + + ",\n"; + message += addListEntry(FIELD.ID.PERCENT_PROGRESS, + status.percentProgress) + + "\n\n"; + } + } + return message; + }, + getManualTasks : function(requestId) { + $log.debug("MsoService:getManualTasks: requestId: " + + requestId); + return $http.get( + "mso/mso_get_man_task/" + requestId, + { + timeout: PropertyService + .getServerResponseTimeoutMsec() + }) + .catch(UtilityService.runHttpErrorHandler); + }, + completeTask: function(taskId, taskToComplete) { + $log.debug("MsoService:completeTask: taskId: " + + taskId); + AaiService.getLoggedInUserID(function (response) { + var attuid = response.data; + var source = "VID"; + var data = { + requestDetails: { + requestInfo: { + source: source, + responseValue: taskToComplete, + requestorId: attuid + } + } + }; + + return $http.post( + "mso/mso_post_man_task/" + taskId, data, + { + timeout: PropertyService + .getServerResponseTimeoutMsec() + }) + .catch(UtilityService.runHttpErrorHandler); + }); + }, + showResponseContentError : function(error, showFunction) { + switch (error.type) { + case "undefinedObject": + showFunction(FIELD.ERROR.SYSTEM_FAILURE, error.message); + break; + case "msoFailure": + showFunction(FIELD.ERROR.MSO, "") + break; + default: + showFunction(FIELD.ERROR.SYSTEM_FAILURE); + } + }, + activateInstance: activateInstance + } +}; appDS2.factory("MsoService", [ "$http", "$log", "PropertyService", - "UtilityService", "COMPONENT", "FIELD", MsoService ]); + "AaiService", "UtilityService", "COMPONENT", "FIELD", "$q", MsoService ]); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/services/schedulerService.js b/vid-app-common/src/main/webapp/app/vid/scripts/services/schedulerService.js new file mode 100644 index 000000000..83cc4ddac --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/services/schedulerService.js @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +"use strict"; + +var SchedulerService = function($http, $log, PropertyService, UtilityService, COMPONENT, FIELD) { + return { + + getStatusSchedulerId : function(schedulerInfo,successCallbackFunction) { + $log + .debug("SchedulerService:getSchedulerStatusAndSchedulerId"); + var url = COMPONENT.POST_CREATE_NEW_VNF_CHANGE+COMPONENT.ASSIGN + Math.random(); + + $http.post(url, schedulerInfo, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data) { + successCallbackFunction(response); + } else { + successCallbackFunction([]); + } + })["catch"] + (UtilityService.runHttpErrorHandler); + }, + + getTimeSotsForSchedulerId:function(schedulerID,successCallbackFunction){ + $log + .debug("SchedulerService:getTimeSlotsForSchedulerID"); + var url = COMPONENT.GET_TIME_SLOTS+COMPONENT.FORWARD_SLASH +schedulerID+COMPONENT.ASSIGN; + + $http.get(url, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data) { + successCallbackFunction(response); + } else { + successCallbackFunction([]); + } + })["catch"] + + (UtilityService.runHttpErrorHandler); + }, + getSubmitForapprovedTimeslots: function(ApprovedTimeSlotsObj,successCallbackFunction) { + $log + .debug("SchedulerService:getSchedulerStatusAndSchedulerId"); + var url = COMPONENT.SUBMIT_VNF_CHANGE_TIMESLOTS+COMPONENT.ASSIGN + Math.random(); + + $http.post(url, ApprovedTimeSlotsObj, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data) { + successCallbackFunction(response); + } else { + successCallbackFunction([]); + } + })["catch"] + (UtilityService.runHttpErrorHandler); + }, + getPolicyInfo:function(policyName,successCallbackFunction){ + $log + .debug("SchedulerService:getPolicyInfo"); + var url = COMPONENT.GET_POLICY +COMPONENT.ASSIGN + Math.random(); + + $http.post(url, policyName, + { + timeout : PropertyService + .getServerResponseTimeoutMsec() + }).then(function(response) { + if (response.data) { + successCallbackFunction(response); + } else { + successCallbackFunction([]); + } + })["catch"] + (UtilityService.runHttpErrorHandler); + } + } +} + +appDS2.factory("SchedulerService", ["$http", "$log", "PropertyService", + "UtilityService", "COMPONENT", "FIELD", SchedulerService]); diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/view-models/change-management.html b/vid-app-common/src/main/webapp/app/vid/scripts/view-models/change-management.html new file mode 100644 index 000000000..0f42ec874 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/scripts/view-models/change-management.html @@ -0,0 +1,112 @@ + + +
+
+ VNF Changes + +
+
+ +
+ New +
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VNF NameTypeFlowStart timeStatus
+ IN PROGRESS +
{{changeManagement.instanceReferences.vnfInstanceName || 'No-Instance-Name'}}{{changeManagement.requestScope}}{{changeManagement.requestType}}{{changeManagement.startTime}}
+ PENDING +
{{changeManagement.vnfName}}{{changeManagement.scheduleRequest.scheduleName}}{{changeManagement.workflow}}{{changeManagement.startTime}}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VNF NameTypeFlowStart timeStatus
+ FINISHED +
{{changeManagement.instanceReferences.vnfInstanceName || 'No-Instance-Name'}}{{changeManagement.requestScope}}{{changeManagement.requestType}}{{changeManagement.startTime}}
+
+
+
+
+
+
\ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/scripts/view-models/instantiate.htm b/vid-app-common/src/main/webapp/app/vid/scripts/view-models/instantiate.htm index 27622ff6e..71efef1dd 100755 --- a/vid-app-common/src/main/webapp/app/vid/scripts/view-models/instantiate.htm +++ b/vid-app-common/src/main/webapp/app/vid/scripts/view-models/instantiate.htm @@ -105,6 +105,9 @@ + + Activate +
  1. diff --git a/vid-app-common/src/main/webapp/app/vid/styles/angularjs-datetime-picker.css b/vid-app-common/src/main/webapp/app/vid/styles/angularjs-datetime-picker.css new file mode 100644 index 000000000..16bad31e4 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/styles/angularjs-datetime-picker.css @@ -0,0 +1,76 @@ +.angularjs-datetime-picker { + color: #333; + font: normal 14px sans-serif; + border: 1px solid #ddd; + display: inline-block; + background: #fff; + z-index: 99999; +} +.angularjs-datetime-picker > .adp-month { + text-align: center; + line-height: 22px; + padding: 10px; + background: #00aeef; + text-transform: uppercase; + font-weight: bold; + border-bottom: 1px solid #ddd; + position: relative; +} +.angularjs-datetime-picker > .adp-month > button { + color: #555; + font: normal 14px sans-serif; + outline: none; + position: absolute; + background: transparent; + border: none; + cursor: pointer; +} +.angularjs-datetime-picker > .adp-month > button:hover { + color: #333; +} +.angularjs-datetime-picker > .adp-month > button.adp-prev { + left: 10px; +} +.angularjs-datetime-picker > .adp-month > button.adp-next { + right: 10px; +} +.angularjs-datetime-picker > .adp-days { + width: 210px; /* 30 x 7 */ + margin: 10px; + text-align: center; +} +.angularjs-datetime-picker > .adp-days > .adp-day-of-week, .angularjs-datetime-picker > .adp-days > .adp-day { + box-sizing: border-box; + -moz-box-sizing: border-box; + border: 1px solid transparent; + width: 30px; + line-height: 28px; + float: left; + border-radius: 25px; +} +.angularjs-datetime-picker > .adp-days > .adp-day-of-week { + font-weight: bold; +} +.angularjs-datetime-picker > .adp-days > .adp-day:not(.selectable) { + opacity: 0.15; + cursor: default; +} +.angularjs-datetime-picker > .adp-days > .adp-day.selectable { + cursor: pointer; +} +.angularjs-datetime-picker > .adp-days > .adp-day.selected { + background: #e0e0e0; +} +.angularjs-datetime-picker > .adp-days > .adp-day.selectable:hover { + background: #00aeef; +} +.angularjs-datetime-picker > .adp-days:after { + content: ''; + display: block; + clear: left; + height: 0; +} + +.angularjs-datetime-picker input[type=range] { + width: 150px; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/styles/change-management-icons.css b/vid-app-common/src/main/webapp/app/vid/styles/change-management-icons.css new file mode 100644 index 000000000..8c4dbd8c5 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/styles/change-management-icons.css @@ -0,0 +1,82 @@ +@font-face { + font-family: 'icomoon'; + src: url('fonts/icomoon.eot?4cilop'); + src: url('fonts/icomoon.eot?4cilop#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?4cilop') format('truetype'), + url('fonts/icomoon.woff?4cilop') format('woff'), + url('fonts/icomoon.svg?4cilop#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} + +.changes-management [class^="icon-"],.changes-management [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-finished_d:before { + content: "\e90c"; + color: #4ca90c; +} +.icon-noun_573805_cc-03:before { + content: "\e90a"; +} +.icon-scedular:before { + content: "\e90b"; +} +.icon-alert:before { + content: "\e901"; + color: #ffb81c; + cursor: pointer; +} +.icon-close_hover:before { + content: "\e902"; +} +.icon-close:before { + content: "\e903"; + color: #5a5a5a; +} +.icon-dearch_hover:before { + content: "\e904"; + color: #5a5a5a; +} +.icon-pending:before { + content: "\e905"; + color: #00aeef; + cursor: pointer; +} +.icon-plus:before { + content: "\e906"; +} +.icon-process:before { + content: "\e900"; + color: #4ca90c; + font-size: 17px; + cursor: pointer; +} +.icon-search:before { + content: "\e907"; + color: #5a5a5a; +} +.icon-view:before { + content: "\e908"; + color: #959595; + font-size: 16px; + cursor: pointer; +} +.icon-x:before { + content: "\e909"; + color: #cf2a2a; + font-size: 12px; + cursor: pointer; +} diff --git a/vid-app-common/src/main/webapp/app/vid/styles/change-management.css b/vid-app-common/src/main/webapp/app/vid/styles/change-management.css new file mode 100644 index 000000000..68a06ee16 --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/styles/change-management.css @@ -0,0 +1,157 @@ +.body-content-jsp { + margin-top: 35px; + min-height: 500px; + margin-left: 201px; + margin-right: 0px; + background-color: #f8f8f8; +} + +.changes-management { + background: white; + color: #797979; +} + +.changes-management .header { + height: 76px; + padding: 13px 0px 0px 26px; + background: #00aeef; +} + +.changes-management #change-management-headline { + font-family: "Open Sans"; + color: #ffffff; + font-size: 24px; + font-weight: 400; + line-height: 24px; + text-align: left; +} + + +.changes-management .separator { + width: 1px; + font-size: 35px; + background: #00aeef; + border-left: 1px solid #d2d2d2; + margin: 0px 30px 0px 30px; +} + +.changes-management .header .button-container { + display: initial; +} + +.changes-management .header .icon-svg { + display: inline; + color: #ffffff; + position: relative; + top: 9px; +} + +.changes-management .header .button-text { + position: relative; + font-family: "Open Sans"; + color: #ffffff; + font-size: 14px; + font-weight: 400; + line-height: 24px; + text-align: left; + bottom: 5px; + left: 5px; +} + +.changes-management .header .icon-filling { + width: 40px; + height: 40px; + fill: #ffffff; +} + +.changes-management .header .search-changes { + width: 361px; + float: right; + height: 41px; + border: 0px; + background-color: #59c2ed; + color: #ffffff; + margin-right: 15px; + border-radius: 10px; + top: 6px; +} + +.changes-management .header .search-changes::placeholder { + font-family: "Open Sans"; + color: #ffffff; + text-align: left; + font-size: 14px; + line-height: 40px; + font-style: italic; +} + +.att-accordion__toggle { + font-size: 14px; +} + +.jobs-table { + background-color: #f8f8f8; + padding: 40px; +} + +.nav-tabs.nav-justified { + width: 30%; + margin-right:2px; + border:0px; + border-radius:0px; +} + +.uib-tab.nav-item { + border: 1px solid #d2d2d2; + background-color: #f8f8f8; +} + +.uib-tab.nav-item.active { + border-top: 4px solid #00aeef; +} + +.nav-tabs.nav-justified>li>a { + border-radius:0px!important; + border: 0px!important; +} + +.table { + border: 1px solid #eaeaea; + box-sizing: border-box; + background-color: #ffffff; + box-shadow: 0px 2px 7px 0px rgba(34, 31, 31, 0.17); + font-family: "Open Sans"; + color: #5a5a5a; + font-size: 14px; + font-weight: 400; +} + +.table>thead { + background-color: #d2d2d2; + font-family: "Open Sans"; + color: #191919; + font-size: 13px; + font-weight: 600; + line-height: 40px; +} + +.table-headline-row { + font-family: "Open Sans"; + color: #00aeef; + font-size: 14px; + font-weight: 600; + background-color: #eaeaea; + box-shadow: 0px 1px 1px 0px rgba(34, 31, 31, 0.19); +} + +.table-bordered{border:1px solid #eaeaea;} +.table-bordered>tbody>tr>td, +.table-bordered>tbody>tr>th, +.table-bordered>tfoot>tr>td, +.table-bordered>tfoot>tr>th, +.table-bordered>thead>tr>td, +.table-bordered>thead>tr>th{border:1px solid #eaeaea;} + +.centered { + text-align: center; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/styles/common.css b/vid-app-common/src/main/webapp/app/vid/styles/common.css new file mode 100644 index 000000000..8d6fb615b --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/styles/common.css @@ -0,0 +1,3 @@ +html, body { + font-size:14px; +} \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.eot b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.eot new file mode 100644 index 000000000..e57ccc5e7 Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.eot differ diff --git a/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.svg b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.svg new file mode 100644 index 000000000..5d514c47b --- /dev/null +++ b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.svg @@ -0,0 +1,23 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.ttf b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.ttf new file mode 100644 index 000000000..7d0e36d1f Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.ttf differ diff --git a/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.woff b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.woff new file mode 100644 index 000000000..b2d2e64af Binary files /dev/null and b/vid-app-common/src/main/webapp/app/vid/styles/fonts/icomoon.woff differ diff --git a/vid-app-common/src/test/java/org/opencomp/vid/controller/MsoControllerTest.java b/vid-app-common/src/test/java/org/opencomp/vid/controller/MsoControllerTest.java new file mode 100644 index 000000000..9333ac9b0 --- /dev/null +++ b/vid-app-common/src/test/java/org/opencomp/vid/controller/MsoControllerTest.java @@ -0,0 +1,112 @@ +package org.opencomp.vid.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.apache.commons.lang.StringEscapeUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openecomp.portalsdk.core.util.SystemProperties; +import org.openecomp.vid.controller.MsoConfig; +import org.openecomp.vid.controller.MsoController; +import org.openecomp.vid.domain.mso.RequestInfo; +import org.openecomp.vid.factories.MsoRequestFactory; +import org.openecomp.vid.mso.rest.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = {SystemProperties.class , MsoConfig.class}) +public class MsoControllerTest { + + @Autowired + MsoRequestFactory msoRequestFactory; + + @Test + public void testInstanceCreationNew() throws Exception { + + RequestDetails requestDetails = msoRequestFactory.createMsoRequest("msoRequest.json"); + MsoController msoController = new MsoController(); + ResponseEntity responseEntityNew = msoController.createSvcInstanceNew(null, requestDetails); + ResponseEntity responseEntity = msoController.createSvcInstance(null, requestDetails); + assertEquals(responseEntityNew, responseEntity); + + } + + @Test + public void testInstanceCreationLocalWithRest() throws Exception { + + RequestDetails requestDetails = msoRequestFactory.createMsoRequest("msoRequest.json"); + MsoController msoController = new MsoController(); + ResponseEntity responseEntityNew = msoController.createSvcInstance(null, requestDetails); + ResponseEntity responseEntityRest = msoController.createSvcInstanceNewRest(null, requestDetails); + + assertEquals(responseEntityNew.getBody(), responseEntityRest.getBody()); + + } + + @Test + public void testInstanceCreation() throws Exception { + + RequestDetails requestDetails = msoRequestFactory.createMsoRequest("msoRequest.json"); + MsoController msoController = new MsoController(); + ResponseEntity responseEntity = msoController.createSvcInstance(null, requestDetails); + + + assertEquals(responseEntity.getBody(), "{ \"status\": 200, \"entity\": {\n" + + " \"requestReferences\": {\n" + + " \"instanceId\": \"ba00de9b-3c3e-4b0a-a1ad-0c5489e711fb\",\n" + + " \"requestId\": \"311cc766-b673-4a50-b9c5-471f68914586\"\n" + + " }\n" + + "}}"); + + } + + @Test + public void testGetOrchestrationRequestsForDashboard() throws Exception{ + MsoController msoController = new MsoController(); + List orchestrationRequestsForDashboard = msoController.getOrchestrationRequestsForDashboard(); + + assertEquals(orchestrationRequestsForDashboard.size() , 2); + } + + @Test + public void testGetManualTasksByRequestId() throws Exception{ + MsoController msoController = new MsoController(); + List orchestrationRequestsForDashboard = msoController.getManualTasksByRequestId("za1234d1-5a33-55df-13ab-12abad84e335"); + + assertEquals(orchestrationRequestsForDashboard.get(0).getTaskId() , "daf4dd84-b77a-42da-a051-3239b7a9392c"); + } + + + public void testCompleteManualTask() throws Exception{ // TODO not done yet + RequestInfo requestInfo = new RequestInfo(); + requestInfo.setResponseValue("rollback"); + requestInfo.setRequestorId("abc"); + requestInfo.setSource("VID"); + RequestDetails requestDetails = new RequestDetails(); + requestDetails.setRequestInfo(requestInfo); + MsoController msoController = new MsoController(); + ResponseEntity responseEntity = msoController.manualTaskComplete("daf4dd84-b77a-42da-a051-3239b7a9392c" , requestDetails); + String assertString = "{ \\\"status\\\": 200, \\\"entity\\\": {\\n\" +\n" + + " \" \\\"taskRequestReference\\\": {\\n\" +\n" + + " \" \\\"taskId\\\": \\\"daf4dd84-b77a-42da-a051-3239b7a9392c\\\"\\n\" +\n" + + " \" }\\n\" +\n" + + " \"}\\n\" +\n" + + " \"}"; + assertEquals(responseEntity.getBody() , StringEscapeUtils.unescapeJava(assertString)); + } + + + + + +} diff --git a/vid-app-common/src/test/java/org/opencomp/vid/controller/VidControllerTest.java b/vid-app-common/src/test/java/org/opencomp/vid/controller/VidControllerTest.java index abf44bf77..f89d9cba0 100644 --- a/vid-app-common/src/test/java/org/opencomp/vid/controller/VidControllerTest.java +++ b/vid-app-common/src/test/java/org/opencomp/vid/controller/VidControllerTest.java @@ -11,6 +11,8 @@ import org.openecomp.sdc.tosca.parser.api.ISdcCsarHelper; import org.openecomp.sdc.tosca.parser.exceptions.SdcToscaParserException; import org.openecomp.sdc.tosca.parser.impl.SdcToscaParserFactory; import org.openecomp.sdc.tosca.parser.impl.SdcTypes; +import org.openecomp.vid.aai.AaiClient; +import org.openecomp.vid.aai.AaiResponse; import org.openecomp.vid.asdc.AsdcCatalogException; import org.openecomp.vid.asdc.AsdcClient; import org.openecomp.vid.asdc.parser.ToscaParserImpl2; @@ -41,6 +43,7 @@ public class VidControllerTest { @Autowired private AsdcClient asdcClient; + @Autowired ServletContext context; public class Constants{ @@ -55,6 +58,19 @@ public class VidControllerTest { private ToscaParserImpl2 p2 = new ToscaParserImpl2(); private ObjectMapper om = new ObjectMapper(); + + @Test + public void test() { + AaiClient client = new AaiClient(context); + AaiResponse response = client.getVNFData(); + try { + System.out.println(new ObjectMapper().writeValueAsString(response)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + @Test public void checkPNFFieldsExist() throws SdcToscaParserException { String serviceRoleString = "serviceRole"; diff --git a/vid-app-common/src/test/java/org/openecomp/vid/services/ChangeManagementServiceTest.java b/vid-app-common/src/test/java/org/openecomp/vid/services/ChangeManagementServiceTest.java new file mode 100644 index 000000000..f770ab2ab --- /dev/null +++ b/vid-app-common/src/test/java/org/openecomp/vid/services/ChangeManagementServiceTest.java @@ -0,0 +1,29 @@ +package org.openecomp.vid.services; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openecomp.vid.changeManagement.ChangeManagementRequest; +import org.openecomp.vid.changeManagement.ChangeManagementResponse; +import org.springframework.http.ResponseEntity; + +import junit.framework.Assert; + +import static org.junit.Assert.*; + + +public class ChangeManagementServiceTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void doChangeManagement_requestTypeIsUpdateVnfNotFound_doUpdateAndReturnNull() throws Exception { + + } + +} \ No newline at end of file diff --git a/vid-app-common/src/test/resources/WEB-INF/conf/system.properties b/vid-app-common/src/test/resources/WEB-INF/conf/system.properties index 4fbbe7cf7..6ec60859d 100644 --- a/vid-app-common/src/test/resources/WEB-INF/conf/system.properties +++ b/vid-app-common/src/test/resources/WEB-INF/conf/system.properties @@ -79,7 +79,7 @@ element_map_icon_path = app/fusionapp/icons/ #aai.oldserver.url=https://mtanjv9aaas40.aic.cip.att.com:8443/aai/servers/v3/ #ist servers aai.server.url.base=https://aai-ext1.test.att.com:8443/aai/ -aai.server.url=https://aai-ext1.test.att.com:8443/aai/v10/ +aai.server.url=https://aai-ext1.test.att.com:8443/aai/v11/ aai.oldserver.url.base=https://aai-ext1.test.att.com:8443/aai/servers/ aai.oldserver.url=https://aai-ext1.test.att.com:8443/aai/servers/v3/ aai.truststore.filename=tomcat_keystore @@ -88,6 +88,7 @@ aai.keystore.filename=aai-client-cert.p12 aai.keystore.passwd.x=OBF:1i9a1u2a1unz1lr61wn51wn11lss1unz1u301i6o aai.use.client.cert=true aai.vnf.provstatus=PREPROV,NVTPROV,PROV,CAPPED +aai_get_version_by_invariant_id="service-design-and-creation/models?depth=2&model-invariant-id=" #Cron Schedules have 6 required fields and 1 optional field: # Seconds Minutes Hours Day-of-Month Month Day-of-Week Year @@ -139,17 +140,24 @@ mso.polling.interval.msecs=10000 mso.max.polls=10 mso.user.name=infraportal mso.password.x=OBF:1ghz1kfx1j1w1m7w1i271e8q1eas1hzj1m4i1iyy1kch1gdz -mso.restapi.svc.instance=/serviceInstances/v4 -mso.restapi.vnf.instance=/serviceInstances/v4//vnfs -mso.restapi.network.instance=/serviceInstances/v4//networks -mso.restapi.vf.module.instance=/serviceInstances/v4//vnfs//vfModules -mso.restapi.volume.group.instance=/serviceInstances/v4//vnfs//volumeGroups -mso.restapi.get.orc.req=/orchestrationRequests/v4 -mso.restapi.get.orc.reqs=/orchestrationRequests/v4? +mso.restapi.svc.instance=/serviceInstances/v5 +mso.restapi.vnf.instance=/serviceInstances/v5//vnfs +mso.restapi.network.instance=/serviceInstances/v5//networks +mso.restapi.vf.module.instance=/serviceInstances/v5//vnfs//vfModules +mso.restapi.volume.group.instance=/serviceInstances/v5//vnfs//volumeGroups +mso.restapi.get.orc.req=/orchestrationRequests/v5 +mso.restapi.get.orc.reqs=/orchestrationRequests/v5? +mso.restapi.get.man.tasks=/tasks/v1 vid.truststore.filename=/opt/app/vid/etc/vid_keystore.jks mso.dme2.client.timeout=30000 mso.dme2.client.read.timeout=120000 +scheduler.server.url=http://mtanjv9sdlg10.aic.cip.att.com:8989/scheduler +scheduler.create.new.vnf.change.instance=/v1/ChangeManagement/schedules/ +scheduler.get.time.slots=/v1/ChangeManagement/schedules/ +scheduler.get.schedules=/v1/ChangeManagement/schedules/scheduleDetails/ + + #vid.truststore.filename=/Users/Oren/Downloads/vid_keystore2.jks vid.truststore.passwd.x=OBF:1wgg1wfq1uus1uui1x131x0r1x1v1x1j1uvo1uve1wg81wfi diff --git a/vid-app-common/src/test/resources/WEB-INF/jsp/serviceModels.jsp b/vid-app-common/src/test/resources/WEB-INF/jsp/serviceModels.jsp index 3280bc65a..9fdf75d64 100644 --- a/vid-app-common/src/test/resources/WEB-INF/jsp/serviceModels.jsp +++ b/vid-app-common/src/test/resources/WEB-INF/jsp/serviceModels.jsp @@ -6,6 +6,7 @@ + + + + + + + @@ -35,6 +42,8 @@ + + @@ -51,6 +60,7 @@ + <%@ page import="org.openecomp.vid.mso.*"%> <%@ page import="org.openecomp.portalsdk.core.util.SystemProperties"%> diff --git a/vid-app-common/src/test/resources/WEB-INF/jsp/welcome.jsp b/vid-app-common/src/test/resources/WEB-INF/jsp/welcome.jsp index dcd996892..1396819c7 100644 --- a/vid-app-common/src/test/resources/WEB-INF/jsp/welcome.jsp +++ b/vid-app-common/src/test/resources/WEB-INF/jsp/welcome.jsp @@ -1,4 +1,5 @@ +

    AT&T Domain 2.0 Network


    @@ -19,8 +20,8 @@ VID was originally developed for the October 2016 release by an integrated IT and Labs team, under the direction of Steve Smokowski and Vivian Pressley.

    -

    Contact Us

    - Please click here to contact us. +

    Contact Us

    + Please click here to contact us. diff --git a/vid-app-common/src/test/resources/mso.properties b/vid-app-common/src/test/resources/mso.properties new file mode 100644 index 000000000..8f2bb01a9 --- /dev/null +++ b/vid-app-common/src/test/resources/mso.properties @@ -0,0 +1,16 @@ +mso.server.url=http://mtanjv9moah01-eth0.aic.cip.att.com:8080/ecomp/mso/infra +mso.polling.interval.msecs=2000 +mso.max.polls=3 +mso.user.name=infraportal +mso.password.x=OBF:1ghz1kfx1j1w1m7w1i271e8q1eas1hzj1m4i1iyy1kch1gdz +mso.restapi.svc.instance=/serviceInstances/v3 +mso.restapi.vnf.instance=/serviceInstances/v3//vnfs +mso.restapi.network.instance=/serviceInstances/v3//networks +mso.restapi.vf.module.instance=/serviceInstances/v3//vnfs//vfModules +mso.restapi.volume.group.instance=/serviceInstances/v3//vnfs//volumeGroups +mso.restapi.get.orc.req=/orchestrationRequests/v3 +mso.restapi.get.orc.reqs=/orchestrationRequests/v3? +mso.restapi.get.man.tasks=/tasks/v1 +mso.dme2.client.timeout=30000 +mso.dme2.client.read.timeout=120000 +mso.dme2.server.url=http://mso-api-handler-anap-v1.mso.ecomp.att.com/services/ecomp/mso?version=1607&envContext=TEST&routeOffer=st_mtsnj \ No newline at end of file diff --git a/vid-app-common/src/test/resources/msoRequest.json b/vid-app-common/src/test/resources/msoRequest.json new file mode 100644 index 000000000..c9397f809 --- /dev/null +++ b/vid-app-common/src/test/resources/msoRequest.json @@ -0,0 +1,25 @@ +{ + "requestDetails": { + "requestInfo": { + "instanceName": "KLKLKL", + "source": "VID", + "suppressRollback": false, + "requestorId": "1" + }, + "modelInfo": { + "modelType": "service", + "modelInvariantId": "709d1be4-9a3f-4a29-8c4d-a20465e808a3", + "modelVersionId": "1de57bcf-365a-4ba7-8a51-7377b7144586", + "modelName": "1707vidnf", + "modelVersion": "2.0" + }, + "requestParameters": { + "userParams": [], + "subscriptionServiceType": "HNGATEWAY", + "aLaCarte": true + }, + "subscriberInfo": { + "globalSubscriberId": "21014aa2-9e71128cae7-jl319x" + } + } +} \ No newline at end of file -- cgit 1.2.3-korg