Merge "Add AsyncInstantiationController tests"
authorIttay Stern <ittay.stern@att.com>
Tue, 11 Feb 2020 06:40:18 +0000 (06:40 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 11 Feb 2020 06:40:18 +0000 (06:40 +0000)
343 files changed:
.readthedocs.yaml [new file with mode: 0644]
LICENSE [new file with mode: 0644]
deliveries/pom.xml
docs/.gitignore [new file with mode: 0644]
docs/_static/css/ribbon.css [new file with mode: 0644]
docs/_static/favicon.ico [new file with mode: 0755]
docs/_static/logo_onap_2017.png [new file with mode: 0644]
docs/conf.py [new file with mode: 0644]
docs/conf.yaml [new file with mode: 0644]
docs/release-notes.rst
docs/requirements-docs.txt [new file with mode: 0644]
docs/tox.ini [new file with mode: 0644]
epsdk-app-onap/pom.xml
epsdk-app-onap/src/main/webapp/WEB-INF/conf/system.properties
epsdk-app-onap/src/main/webapp/WEB-INF/fusion/jsp/ebz/ebz_header.jsp
epsdk-app-onap/version.properties
features.properties.md
pom.xml
releases/6.0.1-container.yaml [new file with mode: 0644]
releases/6.0.2-container.yaml [new file with mode: 0644]
version.properties
vid-app-common/pom.xml
vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java
vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java
vid-app-common/src/main/java/org/onap/vid/aai/ServiceInstance.java
vid-app-common/src/main/java/org/onap/vid/asdc/beans/Service.java
vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java
vid-app-common/src/main/java/org/onap/vid/controller/AaiController2.java
vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java
vid-app-common/src/main/java/org/onap/vid/controller/PreLoadController.java [moved from LICENSE.TXT with 54% similarity]
vid-app-common/src/main/java/org/onap/vid/controller/VidController.java
vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt
vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt
vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt
vid-app-common/src/main/java/org/onap/vid/model/ExceptionResponse.java
vid-app-common/src/main/java/org/onap/vid/model/ServiceInstanceSearchResult.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiationTemplate.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java
vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java
vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java
vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java
vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleOrVolumeGroupRequestDetails.kt
vid-app-common/src/main/java/org/onap/vid/properties/FeatureSetsManager.kt [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/properties/Features.java
vid-app-common/src/main/java/org/onap/vid/properties/FeaturesTogglingConfiguration.java
vid-app-common/src/main/java/org/onap/vid/roles/AlwaysValidRoleValidator.java
vid-app-common/src/main/java/org/onap/vid/roles/PermissionProperties.kt [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/roles/Role.java
vid-app-common/src/main/java/org/onap/vid/roles/RoleProvider.java
vid-app-common/src/main/java/org/onap/vid/roles/RoleValidator.java
vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorByOwningEntity.java [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorBySubscriberAndServiceType.java [moved from vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorByRoles.java with 51% similarity]
vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorFactory.java [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorsComposer.kt [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java
vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java
vid-app-common/src/main/java/org/onap/vid/services/InstantiationTemplatesService.java
vid-app-common/src/main/java/org/onap/vid/services/UserParamsContainer.kt [new file with mode: 0644]
vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt
vid-app-common/src/main/java/org/onap/vid/utils/Logging.java
vid-app-common/src/main/webapp/app/vid/external/angular-moment/moment.min.js
vid-app-common/src/main/webapp/app/vid/external/lodash/lodash.min.js
vid-app-common/src/main/webapp/app/vid/scripts/constants/componentConstants.js
vid-app-common/src/main/webapp/app/vid/scripts/controller/InstantiationController.js
vid-app-common/src/main/webapp/app/vid/scripts/controller/ServiceModelController.js
vid-app-common/src/main/webapp/app/vid/scripts/controller/creationDialogController.js
vid-app-common/src/main/webapp/app/vid/scripts/services/dataService.js
vid-app-common/src/test/java/org/onap/vid/aai/SubscriberFilteredResultsTest.java
vid-app-common/src/test/java/org/onap/vid/bl/AaiServiceTest.java [deleted file]
vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java
vid-app-common/src/test/java/org/onap/vid/controller/AaiControllerTest.java
vid-app-common/src/test/java/org/onap/vid/controller/LoggerControllerTest.java
vid-app-common/src/test/java/org/onap/vid/controller/ServicePermissionsTest.java
vid-app-common/src/test/java/org/onap/vid/controller/VidControllerTest.java
vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java
vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java
vid-app-common/src/test/java/org/onap/vid/model/ServiceInstanceSearchResultTest.java
vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/InstantiationModelSerializationTest.java
vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/mso/MsoUtilTest.java
vid-app-common/src/test/java/org/onap/vid/mso/model/RequestParametersVfModuleTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/properties/FeatureSetsManagerTest.kt [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/roles/AlwaysValidRoleValidatorTest.java
vid-app-common/src/test/java/org/onap/vid/roles/RoleProviderTest.java
vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByOwningEntityTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByRolesTest.java [deleted file]
vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorBySubscriberAndServiceTypeTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorFactoryTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorsComposerTest.java [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/services/AAITreeNodeBuilderTest.java
vid-app-common/src/test/java/org/onap/vid/services/AaiServiceImplTest.java
vid-app-common/src/test/java/org/onap/vid/services/AaiServiceTest.java
vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java
vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java
vid-app-common/src/test/java/org/onap/vid/services/InstantiationTemplatesServiceTest.java
vid-app-common/src/test/java/org/onap/vid/services/MsoRequestBuilderTest.java
vid-app-common/src/test/java/org/onap/vid/services/UserParamsContainerTest.kt [new file with mode: 0644]
vid-app-common/src/test/java/org/onap/vid/testUtils/TestUtils.java
vid-app-common/src/test/resources/example.features.properties [new file with mode: 0644]
vid-app-common/src/test/resources/payload_jsons/vfModuleDelete1Create1None1Request.json
vid-app-common/src/test/resources/payload_jsons/vfmodule/replace_vfmodule__payload_to_mso.json
vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json
vid-app-common/src/test/resources/payload_jsons/vfmodule/upgrade_vfmodule_e2e__payload_to_mso.json
vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request.json
vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_instance_name.json
vid-app-common/src/test/resources/payload_jsons/vfmodule_instantiation_request_without_volume_group.json
vid-app-common/src/test/resources/responses/aai/listServicesByOwningEntity.json [new file with mode: 0644]
vid-app-common/src/test/resources/responses/aai/listServicesByProject.json [new file with mode: 0644]
vid-app-common/version.properties
vid-automation/pom.xml
vid-automation/src/main/java/org/onap/sdc/ci/tests/execute/setup/SetupCDTest.java
vid-automation/src/main/java/org/onap/sdc/ci/tests/utilities/GeneralUIUtils.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/BasePresets/BaseMSOPreset.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/aai/PresetAAIGetModelsByOwningEntity.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOBaseDeleteWithCloudConfiguration.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateNetworkALaCarte5G.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateNetworkALaCarteOldViewEdit.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceAlacarte.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceGen2AlacarteService.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceGen2WithNamesAlacarteGroupingService.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateServiceInstanceGen2WithNamesAlacarteService.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVNFInstanceOnlyRelatedServiceInstance.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleALaCarteE2E.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVfModuleWithVolumeGroupALaCarteCypress.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteE2E.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfALaCarteServiceCypress2.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfGroup.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOCreateVnfVlanTagging.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSODeleteALaCarteService.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOOrchestrationRequestsGet5GServiceInstanceAndNetwork.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOOrchestrationRequestsGetByRequestId.java
vid-automation/src/main/java/org/onap/simulator/presetGenerator/presets/mso/PresetMSOOrchestrationRequestsGetByServiceInstanceId.java
vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java
vid-automation/src/main/java/vid/automation/test/infra/Features.java
vid-automation/src/main/java/vid/automation/test/sections/deploy/DeployModernUIBase.java
vid-automation/src/main/java/vid/automation/test/test/ALaCarteflowTest.java
vid-automation/src/main/java/vid/automation/test/test/BrowseASDCTest.java
vid-automation/src/main/java/vid/automation/test/test/ChangeManagementTest.java
vid-automation/src/main/java/vid/automation/test/test/CreateInstanceDialogBaseTest.java
vid-automation/src/main/java/vid/automation/test/test/ModernUITestBase.java [new file with mode: 0644]
vid-automation/src/main/java/vid/automation/test/test/NewServiceInstanceTest.java
vid-automation/src/main/java/vid/automation/test/test/SearchExistingInstanceTest.java
vid-automation/src/main/java/vid/automation/test/test/TemplateInstantiationTest.java [new file with mode: 0644]
vid-automation/src/main/java/vid/automation/test/test/VidBaseTestCase.java
vid-automation/src/main/java/vid/automation/test/test/ViewEditServiceInstanceTest.java
vid-automation/src/main/resources/NewServiceInstanceTest/createNewServiceInstance_macro_validPopupDataAndUI__dynamicFieldsEcompNamingFalse.json
vid-automation/src/main/resources/asyncInstantiation/vidRequestCreateALaCarte.json
vid-automation/src/main/resources/asyncInstantiation/vidRequestCreateALaCarteForTemplate.json [new file with mode: 0644]
vid-automation/src/main/resources/asyncInstantiation/vidRequestCreateALaCarteWithVnf.json
vid-automation/src/main/resources/registration_to_simulator/add_network/mso_add_network_error.json
vid-automation/src/main/resources/registration_to_simulator/create_new_instance/deploy/mso_create_svc_instance.json
vid-automation/src/main/resources/registration_to_simulator/search_for_service_instance/mso_instance_orch_status_req.json
vid-automation/src/main/resources/supplementaryFiles/sample.json
vid-automation/src/test/java/org/onap/vid/api/AaiApiTest.java
vid-automation/src/test/java/org/onap/vid/more/LoggerFormatTest.java
vid-automation/src/test/resources/VnfGroup/ServiceWithVnfGroupsDeleteRequest.json
vid-automation/src/test/resources/VnfGroup/VnfGroupCreate1Delete1None1Request.json
vid-automation/src/test/resources/VnfGroup/deleteServiceWith2VnfGroupsRequest_AndThreeGroupMembers.json
vid-automation/src/test/resources/VnfGroup/payloadTemplate1VnfGroupWith3MembersRequest.json
vid-automation/src/test/resources/VnfGroup/serviceWithVnfGroupCreateRequest.json
vid-automation/src/test/resources/VnfGroup/vnfGroupCreate1VnfGroupAndDelete2VnfGroupsRequest.json
vid-automation/src/test/resources/VnfGroup/vnfGroupWithExistingAndNewVnfMembers.json
vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-lcp-tenant.json [new file with mode: 0644]
vid-automation/src/test/resources/aaiGetInstanceTopology/getServiceInstanceTopologyResult.json
vid-automation/src/test/resources/asyncInstantiation/ServiceTreeForRetry_serviceInstance.json
vid-automation/src/test/resources/asyncInstantiation/ServiceWithFailedServiceInstance.json
vid-automation/src/test/resources/asyncInstantiation/templates__instance_from_template__set_without_modify1.json
vid-automation/src/test/resources/asyncInstantiation/templates__instance_template.json
vid-automation/src/test/resources/asyncInstantiation/vidRequestCreateALaCarte.json
vid-automation/src/test/resources/asyncInstantiation/vidRequestCreateALaCarteWithVnfGroup.json
vid-automation/src/test/resources/asyncInstantiation/vidRequestDelete1Create1Vnf.json
vid-automation/src/test/resources/asyncInstantiation/vidRequestDeleteServiceWithVnf.json
vid-automation/src/test/resources/registration_to_simulator/body_jsons/mso_request_delete_or_unassign_service_instance.json
vid-automation/src/test/resources/viewEdit/ServiceTreeWithMultipleChildren_serviceInstance_withUpdatedLatestVersion.json
vid-automation/src/test/resources/vrf/vrfServiceCreateRequest.json
vid-ext-services-simulator/src/main/resources/download_files/service-PASQUALEVmxVpeBvService488-csar-annotations.zip [deleted file]
vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar.zip [deleted file]
vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar_ecomp_false6.zip [deleted file]
vid-webpack-master/cypress/integration/iFrames/ala-carte.e2e.ts
vid-webpack-master/cypress/integration/iFrames/browse-sdc.e2e.ts
vid-webpack-master/cypress/integration/iFrames/drawingBoard.e2e.ts
vid-webpack-master/cypress/integration/iFrames/instantiation-templates.e2e.ts
vid-webpack-master/cypress/integration/iFrames/instantiation.templates.modal.e2e.ts
vid-webpack-master/cypress/integration/iFrames/retry.e2e.ts
vid-webpack-master/cypress/integration/iFrames/sdncPreload.e2e.ts [new file with mode: 0644]
vid-webpack-master/cypress/integration/iFrames/service.popup.e2e.ts
vid-webpack-master/cypress/integration/iFrames/viewEditUpgradeVfModule.e2e.ts
vid-webpack-master/cypress/integration/iFrames/viewOnlyDrawingBoard.e2e.ts
vid-webpack-master/cypress/integration/iFrames/vnfGroups.e2e.ts
vid-webpack-master/cypress/integration/iFrames/vrf.e2e.ts
vid-webpack-master/cypress/integration/shared/spinner.e2e.ts
vid-webpack-master/cypress/pipeline/group1.txt
vid-webpack-master/cypress/pipeline/run_group2.sh [deleted file]
vid-webpack-master/cypress/pipeline/run_groupRemain.sh [new file with mode: 0644]
vid-webpack-master/cypress/support/application/application.session.actions.ts
vid-webpack-master/cypress/support/index.js
vid-webpack-master/cypress/support/jsonBuilders/mocks/aai.mock.ts
vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/aaiGetModelsByServiceType.json [new file with mode: 0644]
vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/defect710619/expectedResumeWithVGResults.json
vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/flags.cypress.json
vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/vnfGroupBasicServiceInstance.json
vid-webpack-master/cypress/support/steps/drawingBoard/drawingBoardRecreate.steps.ts [new file with mode: 0644]
vid-webpack-master/cypress/support/steps/drawingBoard/general.steps.ts
vid-webpack-master/cypress/support/steps/fill.vfModule.step.ts
vid-webpack-master/cypress/support/uploadFiles/sdncPreLoadFileExample.json [new file with mode: 0644]
vid-webpack-master/package.cypress.json
vid-webpack-master/package.json [changed mode: 0644->0755]
vid-webpack-master/pom.xml
vid-webpack-master/src/app/drawingBoard/drawingBoard.module.ts
vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.html
vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.component.ts
vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/available-models-tree/available-models-tree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.html
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.component.ts
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-header/drawing-board-header.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/dragAndDrop/dragAndDrop.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.component.ts
vid-webpack-master/src/app/drawingBoard/service-planning/drawing-board-tree/drawing-board-tree.html
vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/duplicate/duplicate.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/basic.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/collectionResource/collectionResource.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/collectionResource/collectionResource.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/configuration/configuration.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/configuration/configuration.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/ncf/ncf.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/ncf/ncf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/network/network.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/pnf/pnf.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/pnf/pnf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/relatedVnfMember/relatedVnfMember.info.model.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vfModule/vfModule.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnf/vnf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vnfGrouping/vnfGrouping.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vpn/vpn.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/models/vrf/vrf.model.info.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToInstanceTree/objectToInstanceTree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToModelTree/objectToModelTree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/objectToTree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.spec.ts
vid-webpack-master/src/app/drawingBoard/service-planning/objectsToTree/shared.tree.service.ts
vid-webpack-master/src/app/drawingBoard/service-planning/service-planning.component.ts
vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.html
vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts
vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.html
vid-webpack-master/src/app/shared/components/auditInfoModal/auditInfoModal.component.ts
vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/modal.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/modal.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/ellipsis/ellipsis.component.ts
vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.html
vid-webpack-master/src/app/shared/components/formControls/component/checkbox/checkbox.formControl.component.scss
vid-webpack-master/src/app/shared/components/formControls/component/file/file.formControl.component.ts
vid-webpack-master/src/app/shared/components/formControls/component/input/input.formControl.component.ts
vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service.ts
vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.spec.ts
vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator.ts
vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.spec.ts
vid-webpack-master/src/app/shared/components/genericForm/formControlsServices/vnfGenerator/vnf.control.generator.ts
vid-webpack-master/src/app/shared/components/genericForm/generic-form.component.html
vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.html
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.component.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/generic-form-popup.service.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/basic.popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/network/network.popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/service/service.popup.service.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popup.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.component.html
vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.spec.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.modal.service.ts
vid-webpack-master/src/app/shared/components/genericFormPopup/instantiationTemplatesModal/instantiation.templates.row.model.ts
vid-webpack-master/src/app/shared/components/messageBox/messageBox.component.ts
vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts [new file with mode: 0644]
vid-webpack-master/src/app/shared/components/searchMembersModal/search-elements-modal.component.ts
vid-webpack-master/src/app/shared/components/spinner/spinner.component.html
vid-webpack-master/src/app/shared/components/svg/svg-component.ts
vid-webpack-master/src/app/shared/models/formControlModels/checkboxFormControl.model.ts
vid-webpack-master/src/app/shared/models/formControlModels/formControl.model.ts
vid-webpack-master/src/app/shared/models/formControlModels/formPopupDetails.model.ts
vid-webpack-master/src/app/shared/models/treeNodeModel.ts
vid-webpack-master/src/app/shared/services/aaiService/aai.epics.ts [changed mode: 0644->0755]
vid-webpack-master/src/app/shared/services/aaiService/aai.service.ts
vid-webpack-master/src/app/shared/services/featureFlag/feature-flags.service.ts
vid-webpack-master/src/app/shared/shared.module.ts
vid-webpack-master/src/app/shared/store/module.ts [changed mode: 0644->0755]
vid-webpack-master/src/app/shared/utils/constants.ts
vid-webpack-master/src/app/vlanTagging/form-async/form-async.component.ts
vid-webpack-master/src/app/vlanTagging/network-selector/network-selector.component.ts
vid-webpack-master/src/app/vlanTagging/vlan-tagging.component.ts
vid-webpack-master/src/styles.scss

diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644 (file)
index 0000000..3797dc8
--- /dev/null
@@ -0,0 +1,20 @@
+---
+# .readthedocs.yml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+# Required
+version: 2
+
+formats:
+  - htmlzip
+
+build:
+  image: latest
+
+python:
+  version: 3.7
+  install:
+    - requirements: docs/requirements-docs.txt
+
+sphinx:
+  configuration: docs/conf.py
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..2dbc891
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,11 @@
+Copyright (C) 2017 - 2019 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.
\ No newline at end of file
index ee5c43e..66e7908 100755 (executable)
@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.onap.vid</groupId>
         <artifactId>vid-parent</artifactId>
-        <version>6.0.0-SNAPSHOT</version>
+        <version>6.0.3-SNAPSHOT</version>
     </parent>
 
     <packaging>pom</packaging>
@@ -64,7 +64,7 @@
                                     <descriptor>assembly/assembly-for-plugin.xml</descriptor>
                                 </assembly>
                                 <tags>
-                                    <tag>5.0-STAGING-latest</tag>
+                                    <tag>6.0-STAGING-latest</tag>
                                     <tag>latest</tag>
                                     <tag>${docker.tag}</tag>
                                     <tag>${docker.latest.tag}</tag>
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644 (file)
index 0000000..43ca5b6
--- /dev/null
@@ -0,0 +1,3 @@
+/.tox
+/_build/*
+/__pycache__/*
diff --git a/docs/_static/css/ribbon.css b/docs/_static/css/ribbon.css
new file mode 100644 (file)
index 0000000..6008cb1
--- /dev/null
@@ -0,0 +1,63 @@
+.ribbon {
+  z-index: 1000;
+  background-color: #a00;
+  overflow: hidden;
+  white-space: nowrap;
+  position: fixed;
+  top: 25px;
+  right: -50px;
+  -webkit-transform: rotate(45deg);
+     -moz-transform: rotate(45deg);
+      -ms-transform: rotate(45deg);
+       -o-transform: rotate(45deg);
+          transform: rotate(45deg);
+  -webkit-box-shadow: 0 0 10px #888;
+     -moz-box-shadow: 0 0 10px #888;
+          box-shadow: 0 0 10px #888;
+
+}
+
+.ribbon a {
+  border: 1px solid #faa;
+  color: #fff;
+  display: block;
+  font: bold 81.25% 'Helvetica Neue', Helvetica, Arial, sans-serif;
+  margin: 1px 0;
+  padding: 10px 50px;
+  text-align: center;
+  text-decoration: none;
+  text-shadow: 0 0 5px #444;
+  transition: 0.5s;
+}
+
+.ribbon a:hover {
+  background: #c11;
+  color: #fff;
+}
+
+
+/* override table width restrictions */
+@media screen and (min-width: 767px) {
+
+   .wy-table-responsive table td, .wy-table-responsive table th {
+      /* !important prevents the common CSS stylesheets from overriding
+         this as on RTD they are loaded after this stylesheet */
+      white-space: normal !important;
+   }
+
+   .wy-table-responsive {
+      overflow: visible !important;
+   }
+}
+
+@media screen and (max-width: 767px) {
+    .wy-table-responsive table td {
+        white-space: nowrap;
+    }
+}
+
+/* fix width of the screen */
+
+.wy-nav-content {
+    max-width: none;
+}
diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico
new file mode 100755 (executable)
index 0000000..cb712eb
Binary files /dev/null and b/docs/_static/favicon.ico differ
diff --git a/docs/_static/logo_onap_2017.png b/docs/_static/logo_onap_2017.png
new file mode 100644 (file)
index 0000000..5d064f4
Binary files /dev/null and b/docs/_static/logo_onap_2017.png differ
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644 (file)
index 0000000..8f40e8b
--- /dev/null
@@ -0,0 +1,15 @@
+from docs_conf.conf import *
+
+branch = 'latest'
+master_doc = 'index'
+
+linkcheck_ignore = [
+    'http://localhost',
+]
+
+intersphinx_mapping = {}
+
+html_last_updated_fmt = '%d-%b-%y %H:%M'
+
+def setup(app):
+    app.add_stylesheet("css/ribbon_onap.css")
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644 (file)
index 0000000..ab59281
--- /dev/null
@@ -0,0 +1,7 @@
+---
+project_cfg: onap
+project: onap
+
+# Change this to ReleaseBranchName to modify the header
+default-version: latest
+#
index 58fd74b..f13b79c 100644 (file)
@@ -3,7 +3,7 @@
 VID Release Notes
 =================
 
-Version: El-Alto (6.0.x)
+Version: Frankfurt (6.0.x)
 ------------------------
 **Known Issues**
 
diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt
new file mode 100644 (file)
index 0000000..b3188dd
--- /dev/null
@@ -0,0 +1,15 @@
+tox
+Sphinx
+doc8
+docutils
+setuptools
+six
+sphinx_rtd_theme>=0.4.3
+sphinxcontrib-blockdiag
+sphinxcontrib-needs>=0.2.3
+sphinxcontrib-nwdiag
+sphinxcontrib-seqdiag
+sphinxcontrib-swaggerdoc
+sphinxcontrib-plantuml
+sphinx_bootstrap_theme
+lfdocs-conf
diff --git a/docs/tox.ini b/docs/tox.ini
new file mode 100644 (file)
index 0000000..edac8c3
--- /dev/null
@@ -0,0 +1,22 @@
+[tox]
+minversion = 1.6
+envlist = docs,
+skipsdist = true
+
+[testenv:docs]
+basepython = python3
+deps = -r{toxinidir}/requirements-docs.txt
+commands =
+    sphinx-build -b html -n -d {envtmpdir}/doctrees ./ {toxinidir}/_build/html
+    echo "Generated docs available in {toxinidir}/_build/html"
+whitelist_externals =
+    echo
+    git
+    sh
+
+[testenv:docs-linkcheck]
+basepython = python3
+#deps = -r{toxinidir}/requirements-docs.txt
+commands = echo "Link Checking not enforced"
+#commands = sphinx-build -b linkcheck -d {envtmpdir}/doctrees ./ {toxinidir}/_build/linkcheck
+whitelist_externals = echo
index 95c1ce2..a7ce6b4 100755 (executable)
@@ -8,7 +8,7 @@
         the Portal team. -->
     <groupId>org.onap.vid</groupId>
     <artifactId>epsdk-app-onap</artifactId>
-    <version>6.0.0-SNAPSHOT</version>
+    <version>6.0.3-SNAPSHOT</version>
     <packaging>war</packaging>
     <name>ECOMP SDK Webapp for OpenSource</name>
     <description>ECOMP SDK Web Application for public release</description>
         <encoding>UTF-8</encoding>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <epsdk.version>2.5.0</epsdk.version>
+        <epsdk.version>2.6.0</epsdk.version>
+        <epsdk.overlay.version>2.5.0</epsdk.overlay.version>
         <jackson.version>2.10.1</jackson.version>
         <jackson.databind.version>2.10.1</jackson.databind.version>
-        <springframework.version>5.2.0.RELEASE</springframework.version>
+        <springframework.version>5.2.3.RELEASE</springframework.version>
         <!-- epsdk-core is importing this class, which is only on spring-orm 4 but not in orm 5:
          org.springframework.orm.hibernate4.HibernateTransactionManager
          so following orm.version lets epsdk-core find it -->
         <dependency>
             <groupId>org.onap.portal.sdk</groupId>
             <artifactId>epsdk-app-overlay</artifactId>
-            <version>${epsdk.version}</version>
+            <version>${epsdk.overlay.version}</version>
             <type>war</type>
         </dependency>
         <dependency>
index 393327d..41e50c3 100755 (executable)
@@ -135,7 +135,7 @@ mso.restapi.cloudResourcesRequestsApiRoot=/cloudResourcesRequests/v1
 mso.restapi.operationalEnvironment.cloudResourcesRequests.status=${mso.restapi.cloudResourcesRequestsApiRoot}?requestId=<request_id>
 
 mso.displayTestAPIOnScreen=true
-mso.defaultTestAPI=VNF_API
+mso.defaultTestAPI=GR_API
 mso.maxOpenedInstantiationRequests=200
 mso.asyncPollingIntervalSeconds=1
 refreshTimeInstantiationDashboard=10
index 50a10d6..4571f34 100644 (file)
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
 <%@ page isELIgnored="false"%>
-<%@ page import="org.onap.portalsdk.core.util.SystemProperties"%>
-<%@ page import="org.onap.portalsdk.core.onboarding.util.PortalApiProperties"%>
 <%@ page import="org.onap.portalsdk.core.onboarding.util.PortalApiConstants"%>
-<%@ page import="org.onap.portalsdk.core.domain.MenuData"%>
+<%@ page import="org.onap.portalsdk.core.onboarding.util.PortalApiProperties"%>
+<%@ page import="org.onap.portalsdk.core.util.SystemProperties"%>
 <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/header.css">
 <link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/ebz_header/portal_ebz_header.css">
-<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css" >
+<link rel="stylesheet" type="text/css" href="app/fusion/external/ebz/sandbox/styles/style.css">
 
 
 <%--<script src= "app/fusion/external/ebz/angular_js/angular.js"></script> --%>
                                            "parentMenuId": null,
                                            "url": ""
                                          },
-                                         {
-                                           "menuId": 90,
-                                           "column": 1,
-                                           "text": "Google",
-                                           "parentMenuId": 1,
-                                           "url": "http://google.com"
-                                         },
-                                         {
-                                           "menuId": 91,
-                                           "column": 1,
-                                           "text": "Mike Little's Coffee Cup",
-                                           "parentMenuId": 2,
-                                           "url": "http://coffee.com"
-                                         },
-                                         {
-                                           "menuId": 92,
-                                           "column": 2,
-                                           "text": "Andy and his Astrophotgraphy",
-                                           "parentMenuId": 3,
-                                           "url": "http://nightskypix.com"
-                                         },
-                                         {
-                                           "menuId": 93,
-                                           "column": 1,
-                                           "text": "JSONLint",
-                                           "parentMenuId": 4,
-                                           "url": "http://http://jsonlint.com"
-                                         },
-                                         {
-                                           "menuId": 96,
-                                           "column": 3,
-                                           "text": "3rd Level App1c R200",
-                                           "parentMenuId": 4,
-                                           "url": "http://app1c.com"
-                                         },
-                                         {
-                                           "menuId": 97,
-                                           "column": 1,
-                                           "text": "3rd Level App4b R16",
-                                           "parentMenuId": 5,
-                                           "url": "http://app4b.com"
-                                         },
-                                         {
-                                           "menuId": 98,
-                                           "column": 2,
-                                           "text": "3rd Level App2b R16",
-                                           "parentMenuId": 5,
-                                           "url": "http://app2b.com"
-                                         },
                                          {
                                            "menuId": 99,
                                            "column": 1,
                        $scope.megaMenuDataObject = menuStructureConvert($scope.jsonMenuData);
 //                     $log.debug(JSON.stringify($scope.jsonMenuData));
        }
+
+       LeftMenuService.getLeftMenu().then(function (response) {
+               var menu = {
+                       parentList: JSON.parse(response.data),
+                       childItemList: JSON.parse(response.data2)
+               };
+
+               try {
+
                var childItemList="";
                var parentList = "";
                try{
-                       childItemList = ${menu.childItemList};
-                       parentList = ${menu.parentList};
+                       childItemList = menu.childItemList;
+                       parentList = menu.parentList;
                }catch(err){
                        console.log("ebz_header: failed to get child/parent lists", err);
                }
                $timeout(function() {
                        detectScrollEvent();
                }, 800);
-               
+
+               } catch (e) {
+                       console.log("error happened while trying to get app menu " + e);
+               }
+       }, function (error) {
+               console.log('getLeftMenu failed', error);
+       });
+
        });
        
        app.filter("ellipsis", function(){
index 19ee1fb..ce5339b 100644 (file)
@@ -4,7 +4,7 @@
 
 major=6
 minor=0
-patch=0
+patch=3
 
 base_version=${major}.${minor}.${patch}
 
index e464583..a0f7e25 100644 (file)
 * FLAG_2004_INSTANTIATION_TEMPLATES_POPUP
   Enables a designated Templates selection modal, accessible when creating a new instance through "Browse SDC".
 
+* FLAG_2006_VFM_SDNC_PRELOAD_FILES
+  Enables upload files when SDNC preload checkbox is checked
+
 * FLAG_2002_UNLIMITED_MAX 
   when flag is true and max_instances is not declare than user can add unlimited VND, NETWORK, VFMODULE,
   User can duplicate up to 10 record in single time.
   If the flag is false and max_instances is not declare the max will be 1 else max_instances value.
+
+* FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO
+  On the "audit info" modal (available on Instantiation Status page), shows a link navigating to
+  the read-only RETRY page with more audit info.
+  
+* FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY 
+  When flag is true the user will be provided with edit permissions by owning entity id even the user have no permission by Subscriber,
+  when the flag is false the user provided with edit permission by Subscriber.
+  
+* FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF
+  When flag is true new VF Modules on Alacarte service will inherit LCP-Region and Tenant from parent VNF.
+  When off, user is requested to specify LCP-Region and Tenant for each VF Module.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 62120e1..70fc41c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.vid</groupId>
     <artifactId>vid-parent</artifactId>
-    <version>6.0.0-SNAPSHOT</version>
+    <version>6.0.3-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>vid</name>
 
@@ -86,7 +86,7 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <build.version>6.0.0-SNAPSHOT</build.version>
+        <build.version>6.0.3-SNAPSHOT</build.version>
         <nexusproxy>https://nexus.onap.org</nexusproxy>
         <snapshotNexusPath>content/repositories/snapshots/</snapshotNexusPath>
         <releaseNexusPath>content/repositories/releases/</releaseNexusPath>
diff --git a/releases/6.0.1-container.yaml b/releases/6.0.1-container.yaml
new file mode 100644 (file)
index 0000000..5480e37
--- /dev/null
@@ -0,0 +1,8 @@
+distribution_type: 'container'
+container_release_tag: '6.0.1'
+project: 'vid'
+log_dir: 'vid-maven-docker-stage-master/233/'
+ref: e8414b1fe839291418ead3a7e5a64bf382dc1121
+containers:
+  - name: 'vid'
+    version: '6.0.1-20200109T025909Z'
\ No newline at end of file
diff --git a/releases/6.0.2-container.yaml b/releases/6.0.2-container.yaml
new file mode 100644 (file)
index 0000000..eee3b1c
--- /dev/null
@@ -0,0 +1,8 @@
+distribution_type: 'container'
+container_release_tag: '6.0.2'
+project: 'vid'
+log_dir: 'vid-maven-docker-stage-master/253/'
+ref: 667fbe07aae6f9669127e9e0212f6f83c87b0d0a
+containers:
+  - name: 'vid'
+    version: '6.0.2-20200126T025724Z'
\ No newline at end of file
index 19ee1fb..ce5339b 100644 (file)
@@ -4,7 +4,7 @@
 
 major=6
 minor=0
-patch=0
+patch=3
 
 base_version=${major}.${minor}.${patch}
 
index c935677..94d07db 100755 (executable)
@@ -9,7 +9,7 @@
         inherit from a parent maven module. -->
     <groupId>org.onap.vid</groupId>
     <artifactId>vid-app-common</artifactId>
-    <version>6.0.0-SNAPSHOT</version>
+    <version>6.0.3-SNAPSHOT</version>
     <packaging>war</packaging>
     <name>VID Common</name>
     <description>VID Common code for opensource version</description>
@@ -25,8 +25,9 @@
         <encoding>UTF-8</encoding>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <epsdk.version>2.5.0</epsdk.version>
-        <springframework.version>5.2.0.RELEASE</springframework.version>
+        <epsdk.version>2.6.0</epsdk.version>
+        <epsdk.overlay.version>2.5.0</epsdk.overlay.version>
+        <springframework.version>5.2.3.RELEASE</springframework.version>
         <springframework.orm.version>4.3.22.RELEASE</springframework.orm.version>
         <!-- epsdk-core is importing this class, which is only on spring-orm 4 but not in orm 5:
          org.springframework.orm.hibernate4.HibernateTransactionManager
         <dependency>
             <groupId>org.onap.portal.sdk</groupId>
             <artifactId>epsdk-app-overlay</artifactId>
-            <version>${epsdk.version}</version>
+            <version>${epsdk.overlay.version}</version>
             <type>war</type>
         </dependency>
         <dependency>
             <artifactId>commons-collections4</artifactId>
             <version>4.4</version>
         </dependency>
+        <dependency>
+            <groupId>commons-cli</groupId>
+            <artifactId>commons-cli</artifactId>
+            <version>1.4</version>
+        </dependency>
         <dependency>
             <groupId>org.hamcrest</groupId>
             <artifactId>java-hamcrest</artifactId>
index 1594010..7816446 100644 (file)
@@ -143,13 +143,13 @@ public class AaiClient implements AaiClientInterface {
     }
 
     @Override
-    public AaiResponse getServicesByOwningEntityId(List<String> owningEntityIds){
+    public AaiResponse<OwningEntityResponse> getServicesByOwningEntityId(List<String> owningEntityIds){
         Response resp = doAaiGet(getUrlFromLIst("business/owning-entities?", "owning-entity-id=", owningEntityIds), false);
         return processAaiResponse(resp, OwningEntityResponse.class, null);
     }
 
     @Override
-    public AaiResponse getServicesByProjectNames(List<String> projectNames){
+    public AaiResponse<ProjectResponse> getServicesByProjectNames(List<String> projectNames){
         Response resp = doAaiGet(getUrlFromLIst("business/projects?", "project-name=",  projectNames), false);
         return processAaiResponse(resp, ProjectResponse.class, null);
     }
@@ -528,9 +528,9 @@ public class AaiClient implements AaiClientInterface {
     }
 
     @Override
-    public AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances) {
+    public AaiResponse<Services> getSubscriberData(String subscriberId, boolean omitServiceInstances) {
         String depth = omitServiceInstances ? "1" : "2";
-        AaiResponse subscriberDataResponse;
+        AaiResponse<Services> subscriberDataResponse;
         Response resp = doAaiGet(BUSINESS_CUSTOMERS_CUSTOMER + subscriberId + "?depth=" + depth, false);
         subscriberDataResponse = processAaiResponse(resp, Services.class, null);
         return subscriberDataResponse;
@@ -617,7 +617,7 @@ public class AaiClient implements AaiClientInterface {
         }
     }
 
-    private AaiResponse processAaiResponse(Response resp, Class classType, String responseBody) {
+    private <T> AaiResponse<T> processAaiResponse(Response resp, Class<? extends T> classType, String responseBody) {
         return processAaiResponse(resp, classType, responseBody, VidObjectMapperType.CODEHAUS);
     }
 
index 2a879e2..b4b908c 100644 (file)
@@ -29,7 +29,9 @@ import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironme
 import org.onap.vid.aai.model.AaiGetPnfs.Pnf;
 import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
 import org.onap.vid.aai.model.ModelVer;
+import org.onap.vid.aai.model.OwningEntityResponse;
 import org.onap.vid.aai.model.PortDetailsTranslator;
+import org.onap.vid.aai.model.ProjectResponse;
 import org.onap.vid.aai.model.Properties;
 import org.onap.vid.aai.model.ResourceType;
 import org.onap.vid.model.SubscriberList;
@@ -49,11 +51,11 @@ public interface AaiClientInterface extends ProbeInterface {
 
     AaiResponse<SubscriberList> getAllSubscribers();
 
-    AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances);
+    AaiResponse<Services> getSubscriberData(String subscriberId, boolean omitServiceInstances);
 
     AaiResponse getServices();
 
-    AaiResponse getServicesByOwningEntityId(List<String> owningEntityIds);
+    AaiResponse<OwningEntityResponse> getServicesByOwningEntityId(List<String> owningEntityIds);
 
     AaiResponse<GetTenantsResponse[]> getTenants(String globalCustomerId, String serviceType);
 
@@ -75,7 +77,7 @@ public interface AaiClientInterface extends ProbeInterface {
 
     ModelVer getLatestVersionByInvariantId(String modelInvariantId);
 
-    AaiResponse getServicesByProjectNames(List<String> projectNames);
+    AaiResponse<ProjectResponse> getServicesByProjectNames(List<String> projectNames);
 
     AaiResponse getServiceModelsByDistributionStatus();
 
index bd1a3ac..a4e7de0 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.vid.aai;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import org.onap.vid.aai.model.RelationshipList;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class ServiceInstance {
@@ -50,4 +51,7 @@ public class ServiceInstance {
        @JsonProperty("model-version-id")
        public String modelVersionId;
 
+       @JsonProperty("relationship-list")
+       public RelationshipList relationshipList;
+
 }
index 0d37fb3..f5dd5d8 100644 (file)
@@ -20,6 +20,9 @@
 
 package org.onap.vid.asdc.beans;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
 import java.util.Collection;
 import java.util.UUID;
 
@@ -76,6 +79,9 @@ public class Service {
     private Collection<SubResource> resources;
 
     private String orchestrationType;
+
+    @JsonInclude(NON_NULL)
+    private Boolean isInstantiationTemplateExists;
     
     
     public static class ServiceBuilder {
@@ -204,6 +210,11 @@ public class Service {
         return orchestrationType;
     }
 
+    public Boolean getIsInstantiationTemplateExists() {
+        return isInstantiationTemplateExists;
+    }
+
+
     public void setUuid(String uuid) {
         this.uuid = uuid;
     }
@@ -256,12 +267,17 @@ public class Service {
         this.orchestrationType = orchestrationType;
     }
 
+    public void setIsInstantiationTemplateExists(Boolean isInstantiationTemplateExists) {
+        this.isInstantiationTemplateExists = isInstantiationTemplateExists;
+    }
+
     @Override
     public String toString() {
         return uuid;
     }
 
     @Override
+
     public int hashCode() {
         return UUID.fromString(getUuid()).hashCode();
     }
index 563c9ff..a9ce40b 100644 (file)
@@ -49,7 +49,6 @@ import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
 import org.onap.vid.aai.util.AAIRestInterface;
 import org.onap.vid.model.VersionByInvariantIdsRequest;
 import org.onap.vid.properties.Features;
-import org.onap.vid.roles.Role;
 import org.onap.vid.roles.RoleProvider;
 import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.services.AaiService;
@@ -137,7 +136,7 @@ public class AaiController extends RestrictedBaseController {
 
     @RequestMapping(value = "/aai_get_services", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<String> doGetServices(HttpServletRequest request) throws IOException {
-        RoleValidator roleValidator = RoleValidator.by(roleProvider.getUserRoles(request));
+        RoleValidator roleValidator = roleProvider.getUserRolesValidator(request);
 
         AaiResponse subscriberList = aaiService.getServices(roleValidator);
         return aaiResponseToResponseEntity(subscriberList);
@@ -225,7 +224,7 @@ public class AaiController extends RestrictedBaseController {
     @RequestMapping(value = "/aai_get_full_subscribers", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<String> getFullSubscriberList(HttpServletRequest request) throws IOException {
         ResponseEntity<String> responseEntity;
-        RoleValidator roleValidator = RoleValidator.by(roleProvider.getUserRoles(request));
+        RoleValidator roleValidator = roleProvider.getUserRolesValidator(request);
         SubscriberFilteredResults subscriberList = aaiService.getFullSubscriberList(roleValidator);
         if (subscriberList.getHttpCode() == 200) {
             responseEntity = new ResponseEntity<>(objectMapper.writeValueAsString(subscriberList.getSubscriberList()),
@@ -256,8 +255,7 @@ public class AaiController extends RestrictedBaseController {
     @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET)
     public ResponseEntity<String> getSubscriberDetails(HttpServletRequest request, @PathVariable("subscriberId") String subscriberId,
                                                        @RequestParam(value="omitServiceInstances", required = false, defaultValue = "false") boolean omitServiceInstances) throws IOException {
-        List<Role> roles = roleProvider.getUserRoles(request);
-        RoleValidator roleValidator = RoleValidator.by(roles);
+        RoleValidator roleValidator = roleProvider.getUserRolesValidator(request);
         AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator,
             featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH) && omitServiceInstances);
         String httpMessage = subscriberData.getT() != null ? objectMapper.writeValueAsString(subscriberData.getT()) : subscriberData.getErrorMessage();
@@ -274,8 +272,7 @@ public class AaiController extends RestrictedBaseController {
         @RequestParam(value = "owningEntity", required = false) List<String> owningEntities) throws IOException {
         ResponseEntity responseEntity;
 
-        List<Role> roles = roleProvider.getUserRoles(request);
-        RoleValidator roleValidator = RoleValidator.by(roles);
+        RoleValidator roleValidator = roleProvider.getUserRolesValidator(request);
 
         AaiResponse<ServiceInstancesSearchResults> searchResult = aaiService
             .getServiceInstanceSearchResults(subscriberId, instanceIdentifier, roleValidator, owningEntities, projects);
@@ -404,8 +401,7 @@ public class AaiController extends RestrictedBaseController {
 
         ResponseEntity responseEntity;
         try {
-            List<Role> roles = roleProvider.getUserRoles(request);
-            RoleValidator roleValidator = RoleValidator.by(roles);
+            RoleValidator roleValidator = roleProvider.getUserRolesValidator(request);
             AaiResponse<GetTenantsResponse[]> response = aaiService
                 .getTenants(globalCustomerId, serviceType, roleValidator);
             if (response.getHttpCode() == 200) {
index 6431282..2d7a925 100644 (file)
@@ -33,6 +33,7 @@ import org.onap.vid.model.aaiTree.Network;
 import org.onap.vid.model.aaiTree.RelatedVnf;
 import org.onap.vid.model.aaiTree.VpnBinding;
 import org.onap.vid.properties.Features;
+import org.onap.vid.roles.PermissionPropertiesSubscriberAndServiceType;
 import org.onap.vid.roles.RoleProvider;
 import org.onap.vid.services.AaiService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -94,7 +95,7 @@ public class AaiController2 extends VidRestrictedBaseController {
 
         final boolean isEditPermitted = roleProvider
                 .getUserRolesValidator(request)
-                .isServicePermitted(subscriberId, serviceType);
+                .isServicePermitted(new PermissionPropertiesSubscriberAndServiceType(subscriberId, serviceType));
 
         return new Permissions(isEditPermitted);
     }
index 6c8a372..ce8bbb5 100644 (file)
@@ -33,7 +33,9 @@ import org.onap.vid.model.ServiceInfo;
 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
 import org.onap.vid.mso.MsoResponseWrapper2;
 import org.onap.vid.properties.Features;
+import org.onap.vid.roles.AllPermissionProperties;
 import org.onap.vid.roles.RoleProvider;
+import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.services.AsyncInstantiationBusinessLogic;
 import org.onap.vid.services.AuditService;
 import org.onap.vid.utils.SystemPropertiesWrapper;
@@ -165,8 +167,15 @@ public class AsyncInstantiationController extends VidRestrictedBaseController {
     }
 
     private void throwExceptionIfAccessDenied(ServiceInstantiation request, HttpServletRequest httpServletRequest, String userId) {
-        if (featureManager.isActive(Features.FLAG_1906_INSTANTIATION_API_USER_VALIDATION) && !roleProvider.getUserRolesValidator(httpServletRequest).isServicePermitted(request.getGlobalSubscriberId(), request.getSubscriptionServiceType())) {
-            throw new AccessDeniedException(String.format("User %s is not allowed to make this request", userId));
+        if (featureManager.isActive(Features.FLAG_1906_INSTANTIATION_API_USER_VALIDATION)) {
+            RoleValidator roleValidator = roleProvider.getUserRolesValidator(httpServletRequest);
+            if (!roleValidator.isServicePermitted(new AllPermissionProperties(
+                request.getGlobalSubscriberId(),
+                request.getSubscriptionServiceType(),
+                request.getOwningEntityId()))
+            ) {
+                throw new AccessDeniedException(String.format("User %s is not allowed to make this request", userId));
+            }
         }
     }
 }
similarity index 54%
rename from LICENSE.TXT
rename to vid-app-common/src/main/java/org/onap/vid/controller/PreLoadController.java
index f79fe7e..ba20997 100644 (file)
@@ -1,24 +1,34 @@
-/*
- * ============LICENSE_START==========================================
- * ===================================================================
- * Copyright Â© 2018 AT&T Intellectual Property. All rights reserved.
- * ===================================================================
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 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
+ *      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============================================
- *
- *
+ * ============LICENSE_END=========================================================
  */
 
-For the file /epsdk-app-onap/src/main/webapp/app/fusion/external/ebz/angular_js/angular-sanitize.js, 
-to the extent that it contains code originating from Erik Arvidsson, that code is used under the Apache-2.0 license, 
-as permitted by http://erik.eae.net/simplehtmlparser/simplehtmlparser.js.
\ No newline at end of file
+package org.onap.vid.controller;
+import org.springframework.web.bind.annotation.*;
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@RequestMapping(PreLoadController.PRE_LOAD)
+public class PreLoadController extends VidRestrictedBaseController{
+    public static final String PRE_LOAD = "preload";
+
+    @PostMapping()
+    public Boolean postPreload (HttpServletRequest request) {
+        return true;
+    }
+}
index 15bc5ed..d257000 100644 (file)
 
 package org.onap.vid.controller;
 
+import java.util.Collection;
 import org.onap.portalsdk.core.controller.RestrictedBaseController;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.vid.asdc.AsdcCatalogException;
 import org.onap.vid.asdc.beans.SecureServices;
+import org.onap.vid.asdc.beans.Service;
 import org.onap.vid.exceptions.VidServiceUnavailableException;
 import org.onap.vid.model.PombaInstance.PombaRequest;
 import org.onap.vid.model.ServiceModel;
 import org.onap.vid.roles.Role;
 import org.onap.vid.roles.RoleProvider;
 import org.onap.vid.services.AaiService;
+import org.onap.vid.services.InstantiationTemplatesService;
 import org.onap.vid.services.PombaService;
 import org.onap.vid.services.VidService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,14 +53,16 @@ public class VidController extends RestrictedBaseController {
     private final AaiService aaiService;
     private final RoleProvider roleProvider;
     private final PombaService pombaService;
+    private final InstantiationTemplatesService instantiationTemplatesService;
 
     @Autowired
     public VidController(VidService vidService, AaiService aaiService, RoleProvider roleProvider,
-        PombaService pombaService) {
+        PombaService pombaService, InstantiationTemplatesService instantiationTemplatesService) {
         this.vidService = vidService;
         this.aaiService = aaiService;
         this.roleProvider = roleProvider;
         this.pombaService = pombaService;
+        this.instantiationTemplatesService = instantiationTemplatesService;
     }
 
     /**
@@ -69,8 +74,15 @@ public class VidController extends RestrictedBaseController {
         LOG.info("Start API for browse SDC was called");
         SecureServices secureServices = new SecureServices();
         List<Role> roles = roleProvider.getUserRoles(request);
-        secureServices.setServices(aaiService.getServicesByDistributionStatus());
+
+        Collection<Service> servicesByDistributionStatus = aaiService.getServicesByDistributionStatus();
+
+        Collection<Service> servicesWithTemplatesIndication =
+            instantiationTemplatesService.setOnEachServiceIsTemplateExists(servicesByDistributionStatus);
+
+        secureServices.setServices(servicesWithTemplatesIndication);
                secureServices.setReadOnly(roleProvider.userPermissionIsReadOnly(roles));
+
         return secureServices;
     }
 
index e46a24f..063ef6e 100644 (file)
@@ -11,11 +11,12 @@ import org.onap.vid.changeManagement.RequestDetailsWrapper
 import org.onap.vid.model.serviceInstantiation.*
 import org.onap.vid.mso.model.*
 import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.*
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue
 import org.onap.vid.mso.rest.SubscriberInfo
 import org.onap.vid.properties.Features
 import org.onap.vid.services.AsyncInstantiationBusinessLogic
 import org.onap.vid.services.CloudOwnerService
-import org.onap.vid.utils.JACKSON_OBJECT_MAPPER
+import org.onap.vid.services.UserParamsContainer
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
 import org.togglz.core.manager.FeatureManager
@@ -108,7 +109,7 @@ class MsoRequestBuilder
         //cloud configuration
         val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId)
 
-        val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams)
+        val userParams = UserParamsContainer(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams)
 
         //related instance list
         val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo))
@@ -118,7 +119,7 @@ class MsoRequestBuilder
             relatedInstanceList.add(RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.volumeGroupInstanceName))
         }
 
-        return RequestDetailsWrapper(VfModuleOrVolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters(userParams)))
+        return RequestDetailsWrapper(VfModuleOrVolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters(userParams.toALaCarte())))
     }
 
     fun generateVfModuleInstantiationRequest(
@@ -153,8 +154,8 @@ class MsoRequestBuilder
     fun generateVolumeGroupInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper<VolumeGroupRequestDetails> {
         val requestInfo = generateRequestInfo(vfModuleDetails.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, vfModuleDetails.isRollbackOnFailure, null, userId)
         val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId)
-        val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams)
-        val requestParameters = RequestParametersVfModuleOrVolumeGroupInstantiation(userParams, vfModuleDetails.isUsePreload, testApi)
+        val userParams = UserParamsContainer(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams)
+        val requestParameters = RequestParametersVfModuleOrVolumeGroupInstantiation(userParams.toALaCarte(), vfModuleDetails.isUsePreload, testApi)
         val relatedInstances = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo))
 
         vfModuleDetails.modelInfo.modelType = "volumeGroup"
@@ -283,39 +284,17 @@ class MsoRequestBuilder
     private fun convertVfModuleMapToList(vfModules: Map<String, Map<String, VfModule>>): List<VfModuleMacro> {
         return vfModules.values.stream().flatMap { vfModule ->
             vfModule.values.stream().map { item ->
-                val aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.instanceParams), item.supplementaryParams)
-                val aggregatedParamsConverted = JACKSON_OBJECT_MAPPER.convertValue(aggregatedParams, List::class.java)
+                val userParams = UserParamsContainer(extractActualInstanceParams(item.instanceParams), item.supplementaryParams)
 
                 VfModuleMacro(
                         item.modelInfo,
                         item.instanceName,
                         item.volumeGroupInstanceName,
-                        aggregatedParamsConverted as List<Map<String, String>>)
+                        userParams.toMacroPost1806())
             }
         }.collect(Collectors.toList<VfModuleMacro>())
     }
 
-    fun aggregateAllInstanceParams(instanceParams: Map<String, String>?, supplementaryParams: Map<String, String>?): List<UserParamMap<String, String>> {
-        var instanceParamsFinal: Map<String, String> = instanceParams ?: emptyMap()
-        val supplementaryParamsFinal: Map<String, String> = supplementaryParams ?: emptyMap()
-
-        if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) {
-            //remove duplicate keys from instanceParams if exist in supplementaryParams
-            instanceParamsFinal = instanceParamsFinal.entries.stream()
-                    .filter { m -> !supplementaryParamsFinal.containsKey(m.key) }
-                    .collect(Collectors.toMap({ it.key }, { it.value }))
-
-            //aggregate the 2 collections and format them as UserParamMap
-            val aggregatedParams = UserParamMap<String, String>()
-            aggregatedParams.putAll(instanceParamsFinal)
-            aggregatedParams.putAll(supplementaryParamsFinal)
-
-            return mutableListOf(aggregatedParams)
-        }
-
-        return emptyList()
-    }
-
     //Make sure we always get a one Map from InstanceParams
     private fun extractActualInstanceParams(originalInstanceParams: List<MutableMap<String, String>>?): MutableMap<String, String> {
         return if (originalInstanceParams.isNullOrEmpty() || originalInstanceParams[0].isNullOrEmpty()) {
@@ -394,14 +373,14 @@ class MsoRequestBuilder
         }
     }
 
-    private fun generateUserParamList(): List<ServiceInstantiationRequestDetails.UserParamNameAndValue> {
+    private fun generateUserParamList(): List<UserParamNameAndValue> {
         return emptyList()
     }
 
     fun generateMacroServicePre1806InstantiationRequest(payload: ServiceInstantiation, userId: String): RequestDetailsWrapper<ServiceInstantiationRequestDetails> {
         val requestInfo = ServiceInstantiationRequestDetails.RequestInfo(payload.instanceName, payload.productFamilyId, VID_SOURCE, payload.isRollbackOnFailure, userId)
-        val userParams = generateUserParamsNameAndValue(payload.instanceParams)
-        val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, userParams)
+        val userParams = UserParamsContainer(generateSingleMapFromInstanceParams(payload.instanceParams), emptyList())
+        val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, userParams.toMacroPre1806())
         val subscriberInfo = generateSubscriberInfoPre1806(payload)
         val project = if (payload.projectName != null) ServiceInstantiationRequestDetails.Project(payload.projectName) else null
         val owningEntity = ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.owningEntityId, payload.owningEntityName)
@@ -419,8 +398,8 @@ class MsoRequestBuilder
                 relatedInstanceList))
     }
 
-    private fun generateUserParamsNameAndValue(instanceParams: List<Map<String, String>>): List<ServiceInstantiationRequestDetails.UserParamNameAndValue> {
-        return instanceParams.getOrElse(0) {emptyMap()}.map{ x-> ServiceInstantiationRequestDetails.UserParamNameAndValue(x.key, x.value)}
+    private fun generateSingleMapFromInstanceParams(instanceParams: List<Map<String, String>>): Map<String, String> {
+        return if (instanceParams.isNullOrEmpty()) emptyMap() else instanceParams[0]
     }
 
     private fun generateSubscriberInfoPre1806(payload: ServiceInstantiation): SubscriberInfo {
index 731625c..68c9f53 100644 (file)
@@ -207,9 +207,6 @@ class VfmoduleCommand @Autowired constructor(
         val serviceModelInfo = serviceModelInfoFromRequest()
         val modelNewestUuid = commandUtils.getNewestModelUuid(serviceModelInfo.modelInvariantId);
 
-        check(!modelNewestUuid.equals(serviceModelInfo.modelVersionId, true)) {
-            "Model version id ${serviceModelInfo.modelVersionId} is already the latest version of model's invariant id ${serviceModelInfo.modelInvariantId}" }
-
         val serviceNewestModel = commandUtils.getServiceModel(modelNewestUuid);
 
         return serviceNewestModel;
index 48ff7b7..b008c13 100644 (file)
@@ -12,6 +12,7 @@ import org.onap.vid.model.serviceInstantiation.Vnf
 import org.onap.vid.mso.RestMsoImplementation
 import org.onap.vid.properties.Features
 import org.onap.vid.services.AsyncInstantiationBusinessLogic
+import org.onap.vid.utils.isNotActive
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.beans.factory.config.ConfigurableBeanFactory
 import org.springframework.context.annotation.Scope
@@ -59,9 +60,9 @@ class VnfCommand @Autowired constructor(
             val vfModules:List<VfModule> = request.vfModules.values.stream().flatMap { vfKey -> vfKey.values.stream() }.collect(Collectors.toList<VfModule>())
 
             try {
-                childJobs = pushChildrenJobsToBroker(vfModules.filter { filterModuleByNeedToCreateBase(it) }, dataForChild, JobType.VolumeGroupInstantiation)
+                childJobs = pushChildrenJobsToBroker(vfModulesForChildrenJobs(vfModules), dataForChild, JobType.VolumeGroupInstantiation)
             } catch (e: AsdcCatalogException) {
-                LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e)
+                LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message, e)
                 //return Job.JobStatus.FAILED
                 throw e;
             }
@@ -70,11 +71,26 @@ class VnfCommand @Autowired constructor(
         return Job.JobStatus.COMPLETED_WITH_NO_ACTION
     }
 
-    private fun filterModuleByNeedToCreateBase(it: VfModule):Boolean {
+    private fun vfModulesForChildrenJobs(vfModules: List<VfModule>): List<VfModule> =
+            vfModules
+                    .filter { filterModuleByNeedToCreateBase(it) }
+                    .map { childVfModuleWithVnfRegionAndTenant(it) }
+
+    internal fun childVfModuleWithVnfRegionAndTenant(vfModule: VfModule): VfModule {
+        if (featureManager.isNotActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)) {
+            return vfModule
+        }
+
+        val vnfLcpCloudRegionId = getRequest().lcpCloudRegionId
+        val vnfTenantId = getRequest().tenantId
+        return vfModule.cloneWith(vnfLcpCloudRegionId, vnfTenantId)
+    }
+
+    private fun filterModuleByNeedToCreateBase(vfModule: VfModule): Boolean {
         return needToCreateBaseModule ==
-            commandUtils.isVfModuleBaseModule(
-                    serviceModelInfoFromRequest().modelVersionId,
-                    it.modelInfo.modelVersionId)
+                commandUtils.isVfModuleBaseModule(
+                        serviceModelInfoFromRequest().modelVersionId,
+                        vfModule.modelInfo.modelVersionId)
     }
 
     override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan {
index d2e5d63..f8d5918 100644 (file)
 
 package org.onap.vid.model;
 
+import org.onap.logging.ref.slf4j.ONAPLogConstants.MDCs;
 import org.slf4j.MDC;
 
-import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
-
 /**
  * The Class ExceptionResponse.
  */
@@ -67,7 +66,7 @@ public class ExceptionResponse {
 
        public void setException(Exception exception) {
                setException(exception.getClass().toString().replaceFirst("^.*[\\.$]", ""));
-               setMessage(exception.getMessage() + " (Request id: " + MDC.get(MDC_KEY_REQUEST_ID) + ")");
+               setMessage(exception.getMessage() + " (Request id: " + MDC.get(MDCs.REQUEST_ID) + ")");
        }
 
        /**
index 259405c..f750279 100644 (file)
 
 package org.onap.vid.model;
 
-public class ServiceInstanceSearchResult {
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.vid.roles.WithPermissionPropertiesOwningEntity;
+import org.onap.vid.roles.WithPermissionPropertiesSubscriberAndServiceType;
+
+public class ServiceInstanceSearchResult
+       implements WithPermissionPropertiesSubscriberAndServiceType, WithPermissionPropertiesOwningEntity {
+
+       private final String SUBSCRIBER_ID_FRONTEND_ALIAS = "globalCustomerId";
 
        private String serviceInstanceId;
 
-       private String globalCustomerId;
+       private String subscriberId;
 
        private String serviceType;
 
@@ -36,21 +44,24 @@ public class ServiceInstanceSearchResult {
 
        private String aaiModelVersionId;
 
+       private String owningEntityId;
+
        private boolean isPermitted;
 
        public ServiceInstanceSearchResult(){
-
        }
-       public ServiceInstanceSearchResult(String serviceInstanceId, String globalCustomerId, String serviceType,
-                                                                          String serviceInstanceName, String subscriberName, String aaiModelInvariantId,
-                                                                          String aaiModelVersionId, boolean isPermitted) {
+       
+       public ServiceInstanceSearchResult(String serviceInstanceId, String subscriberId, String serviceType,
+               String serviceInstanceName, String subscriberName, String aaiModelInvariantId,
+               String aaiModelVersionId, String owningEntityId, boolean isPermitted) {
                this.serviceInstanceId = serviceInstanceId;
-               this.globalCustomerId = globalCustomerId;
+               this.subscriberId = subscriberId;
                this.serviceType = serviceType;
                this.serviceInstanceName = serviceInstanceName;
                this.subscriberName = subscriberName;
                this.aaiModelInvariantId = aaiModelInvariantId;
                this.aaiModelVersionId = aaiModelVersionId;
+               this.owningEntityId = owningEntityId;
                this.isPermitted = isPermitted;
        }
 
@@ -62,14 +73,17 @@ public class ServiceInstanceSearchResult {
                this.serviceInstanceId = serviceInstanceId;
        }
 
-       public String getGlobalCustomerId() {
-               return globalCustomerId;
+       @Override
+       @JsonProperty(SUBSCRIBER_ID_FRONTEND_ALIAS)
+       public String getSubscriberId() {
+               return subscriberId;
        }
 
-       public void setGlobalCustomerId(String globalCustomerId) {
-               this.globalCustomerId = globalCustomerId;
+       public void setSubscriberId(String subscriberId) {
+               this.subscriberId = subscriberId;
        }
 
+       @Override
        public String getServiceType() {
                return serviceType;
        }
@@ -110,6 +124,15 @@ public class ServiceInstanceSearchResult {
                this.aaiModelVersionId = aaiModelVersionId;
        }
 
+       @Override
+       public String getOwningEntityId() {
+               return owningEntityId;
+       }
+
+       public void setOwningEntityId(String owningEntityId) {
+               this.owningEntityId = owningEntityId;
+       }
+
        public boolean getIsPermitted() {
                return isPermitted;
        }
@@ -119,21 +142,21 @@ public class ServiceInstanceSearchResult {
        }
 
        @Override
-       public boolean equals(Object other){
-               if (other instanceof ServiceInstanceSearchResult) {
-                       ServiceInstanceSearchResult serviceInstanceSearchResultOther = (ServiceInstanceSearchResult) other;
-                       if (this.getServiceInstanceId().equals(serviceInstanceSearchResultOther.getServiceInstanceId())) {
-                               return true;
-                       }
+       public boolean equals(Object o{
+               if (this == o) {
+                       return true;
+               }
+               if (o == null || getClass() != o.getClass()) {
+                       return false;
                }
-               return false;
 
+               ServiceInstanceSearchResult that = (ServiceInstanceSearchResult) o;
+
+               return StringUtils.equals(serviceInstanceId, that.serviceInstanceId);
        }
 
        @Override
        public int hashCode() {
-               int result = 17;
-               result = 31 * result + serviceInstanceId.hashCode();
-               return result;
+               return serviceInstanceId != null ? serviceInstanceId.hashCode() : 0;
        }
 }
index 1079fbe..7617d77 100644 (file)
 
 package org.onap.vid.model.serviceInstantiation;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.collect.ImmutableMap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.vid.job.JobAdapter;
 import org.onap.vid.job.JobType;
 import org.onap.vid.model.Action;
 import org.onap.vid.mso.model.ModelInfo;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
 public abstract class BaseResource implements JobAdapter.AsyncJobRequest {
 
        protected String instanceId;
@@ -60,6 +62,9 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest {
 
        protected Integer position;
 
+       @JsonInclude(NON_NULL)
+       protected String originalName; //not used at backend, but stored for fronted
+
 
        private static final Map<String, Action> actionStingToEnumMap = ImmutableMap.<String, Action>builder()
                        .put("Delete", Action.Delete)
@@ -85,7 +90,8 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest {
                @JsonProperty("trackById") String trackById,
                @JsonProperty("isFailed") Boolean isFailed,
                @JsonProperty("statusMessage") String statusMessage,
-               @JsonProperty("position") Integer position) {
+               @JsonProperty("position") Integer position,
+               @JsonProperty("originalName") String originalName) {
                this.modelInfo = modelInfo;
                this.modelInfo.setModelType(getModelType());
                this.rollbackOnFailure = rollbackOnFailure;
@@ -99,6 +105,7 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest {
                this.isFailed = isFailed!= null ? isFailed: false;
                this.statusMessage = statusMessage;
                this.position = position;
+               this.originalName = originalName;
        }
 
        private Action actionStringToEnum(String actionAsString) {
@@ -177,6 +184,10 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest {
                this.position = position;
        }
 
+       public String getOriginalName() {
+               return originalName;
+       }
+
        @JsonIgnore
        public abstract Collection<? extends BaseResource> getChildren();
 
index f23c2e7..642e28b 100644 (file)
 package org.onap.vid.model.serviceInstantiation;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import org.onap.vid.job.JobAdapter;
-import org.onap.vid.job.JobType;
-import org.onap.vid.mso.model.ModelInfo;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
+import org.onap.vid.job.JobAdapter;
+import org.onap.vid.job.JobType;
+import org.onap.vid.mso.model.ModelInfo;
 
 public class InstanceGroup extends BaseResource implements JobAdapter.AsyncJobRequest {
 
@@ -42,10 +41,11 @@ public class InstanceGroup extends BaseResource implements JobAdapter.AsyncJobRe
         @JsonProperty("trackById") String trackById,
         @JsonProperty("isFailed") Boolean isFailed,
         @JsonProperty("statusMessage") String statusMessage,
-        @JsonProperty("position") Integer position) {
+        @JsonProperty("position") Integer position,
+        @JsonProperty("originalName") String originalName) {
 
         super(modelInfo, instanceName, action, null, null, null, null, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage,
-            position);
+            position, originalName);
         this.vnfGroupMembers = vnfGroupMembers;
     }
 
index e9f34cc..758ee06 100644 (file)
@@ -34,9 +34,10 @@ public class InstanceGroupMember extends BaseResource implements JobAdapter.Asyn
         @JsonProperty("trackById") String trackById,
         @JsonProperty("isFailed") Boolean isFailed,
         @JsonProperty("statusMessage") String statusMessage,
-        @JsonProperty("position") Integer position) {
+        @JsonProperty("position") Integer position,
+        @JsonProperty("originalName") String originalName) {
         super(new ModelInfo(), null, action, null, null, null, null, false, instanceId, trackById, isFailed, statusMessage,
-            position);
+            position, originalName);
     }
 
     @Override
index b9a0aeb..cec61f6 100644 (file)
 package org.onap.vid.model.serviceInstantiation;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import org.onap.vid.job.JobAdapter;
-import org.onap.vid.job.JobType;
-import org.onap.vid.mso.model.ModelInfo;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import org.onap.vid.job.JobAdapter;
+import org.onap.vid.job.JobType;
+import org.onap.vid.mso.model.ModelInfo;
 
 public class Network extends BaseResource implements JobAdapter.AsyncJobRequest {
 
@@ -53,10 +52,11 @@ public class Network extends BaseResource implements JobAdapter.AsyncJobRequest
                @JsonProperty("trackById") String trackById,
                @JsonProperty("isFailed") Boolean isFailed,
                @JsonProperty("statusMessage") String statusMessage,
-               @JsonProperty("position") Integer position) {
+               @JsonProperty("position") Integer position,
+               @JsonProperty("originalName") String originalName) {
 
                super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage,
-            position);
+            position, originalName);
                this.productFamilyId = productFamilyId;
                this.platformName = platformName;
                this.lineOfBusiness = lineOfBusiness;
index e7e5783..7c04a91 100644 (file)
@@ -104,9 +104,10 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy
                                 @JsonProperty("trackById") String trackById,
                                 @JsonProperty("isFailed") Boolean isFailed,
                                 @JsonProperty("statusMessage") String statusMessage,
-                                @JsonProperty("vidNotions") VidNotions vidNotions) {
+                                @JsonProperty("vidNotions") VidNotions vidNotions,
+                                @JsonProperty("originalName") String originalName) {
         super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage,
-            null);
+            null, originalName);
         this.owningEntityId = owningEntityId;
         this.owningEntityName = owningEntityName;
         this.projectName = projectName;
index 4872ce2..9499beb 100644 (file)
@@ -52,7 +52,8 @@ public class ServiceInstantiationTemplate extends ServiceInstantiation implement
             baseService.isRollbackOnFailure(), baseService.isALaCarte(), baseService.getTestApi(),
             baseService.getInstanceId(), Objects.toString(baseService.getAction(), null),
             baseService.getTrackById(), baseService.getIsFailed(), baseService.getStatusMessage(),
-            baseService.getVidNotions()
+            baseService.getVidNotions(),
+            baseService.getOriginalName()
         );
 
         this.existingVNFCounterMap = vnfCounterMap;
index 89e25e6..79ea7f1 100644 (file)
@@ -33,6 +33,7 @@ import javax.annotation.Nullable;
 import org.onap.vid.job.JobAdapter;
 import org.onap.vid.job.JobType;
 import org.onap.vid.mso.model.ModelInfo;
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue;
 
 /**
  * The Class VfModule.
@@ -42,7 +43,7 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
 
        @JsonInclude(NON_NULL) @JsonProperty("volumeGroupName") private final String volumeGroupInstanceName;
        @JsonInclude(NON_NULL) @JsonProperty("sdncPreLoad") private Boolean usePreload;
-       private Map<String, String> supplementaryParams;
+       private List<UserParamNameAndValue> supplementaryParams;
 
        @JsonInclude(NON_NULL)
        private final Boolean retainVolumeGroups;
@@ -58,7 +59,7 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
                @JsonProperty("legacyRegion") String legacyRegion,
                @JsonProperty("tenantId") String tenantId,
                @JsonProperty("instanceParams") List<Map<String, String>> instanceParams,
-               @JsonProperty("supplementaryFileContent") Map<String, String> supplementaryParams,
+               @JsonProperty("supplementaryFileContent") List<UserParamNameAndValue> supplementaryParams,
                @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure,
                @JsonProperty("sdncPreLoad") @JsonAlias("usePreload") Boolean usePreload,
                @JsonProperty("instanceId") String instanceId,
@@ -67,9 +68,10 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
                @JsonProperty("statusMessage") String statusMessage,
                @Nullable @JsonProperty("retainAssignments") Boolean retainAssignments,
                @Nullable @JsonProperty("retainVolumeGroups") Boolean retainVolumeGroups,
-               @JsonProperty("position") Integer position) {
+               @JsonProperty("position") Integer position,
+               @JsonProperty("originalName") String originalName) {
                super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage,
-                       position);
+                       position, originalName);
                this.volumeGroupInstanceName = volumeGroupInstanceName;
                this.usePreload = usePreload;
                this.supplementaryParams = supplementaryParams;
@@ -86,7 +88,7 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
                return usePreload;
        }
 
-       public Map<String, String> getSupplementaryParams() {
+       public List<UserParamNameAndValue> getSupplementaryParams() {
                return supplementaryParams;
        }
 
@@ -134,6 +136,32 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest
                                this.getStatusMessage(),
                                this.isRetainAssignments(),
                                this.isRetainVolumeGroups(),
-                               this.getPosition());
+                               this.getPosition(),
+                           this.getOriginalName()
+               );
+       }
+
+       public VfModule cloneWith(String lcpCloudRegionId, String tenantId) {
+               return new VfModule(
+                       this.getModelInfo(),
+                       this.getInstanceName(),
+                       this.getVolumeGroupInstanceName(),
+                       this.getAction().toString(),
+                       lcpCloudRegionId,
+                       lcpCloudRegionId,
+                       tenantId,
+                       this.getInstanceParams(),
+                       this.getSupplementaryParams(),
+                       this.isRollbackOnFailure(),
+                       this.isUsePreload(),
+                       this.getInstanceId(),
+                       this.getTrackById(),
+                       this.getIsFailed(),
+                       this.getStatusMessage(),
+                       this.isRetainAssignments(),
+                       this.isRetainVolumeGroups(),
+                       this.getPosition(),
+                       this.getOriginalName()
+               );
        }
 }
\ No newline at end of file
index fc71f27..2ed2196 100644 (file)
 package org.onap.vid.model.serviceInstantiation;
 
 
+import static java.util.stream.Collectors.toList;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import org.onap.vid.job.JobAdapter;
 import org.onap.vid.job.JobType;
 import org.onap.vid.mso.model.ModelInfo;
 
-import java.util.*;
-
-import static java.util.stream.Collectors.toList;
-
 /**
  * The Class VNF.
  */
@@ -59,10 +62,11 @@ public class Vnf extends BaseResource implements JobAdapter.AsyncJobRequest {
                @JsonProperty("trackById") String trackById,
                @JsonProperty("isFailed") Boolean isFailed,
                @JsonProperty("statusMessage") String statusMessage,
-               @JsonProperty("position") Integer position) {
+               @JsonProperty("position") Integer position,
+               @JsonProperty("originalName") String originalName) {
 
                super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage,
-                       position);
+                       position, originalName);
                this.productFamilyId = productFamilyId;
                this.platformName = platformName;
                this.lineOfBusiness = lineOfBusiness;
index 626816f..8de534a 100644 (file)
 
 package org.onap.vid.mso;
 
+import static org.apache.commons.lang3.StringUtils.firstNonBlank;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 
-import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
 import io.joshworks.restclient.http.HttpResponse;
 import java.io.IOException;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.onap.vid.exceptions.GenericUncheckedException;
 
 public class MsoUtil {
 
@@ -76,22 +76,31 @@ public class MsoUtil {
     }
 
     public static String formatExceptionAdditionalInfo(int statusCode, String msoResponse) {
-        String errorMsg = "Http Code:" + statusCode;
-        if (!StringUtils.isEmpty(msoResponse)) {
-            String filteredJson;
-            try {
-                filteredJson = StringUtils.defaultIfEmpty(
-                        JACKSON_OBJECT_MAPPER.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") ,
-                        msoResponse
-                );
-            } catch (JsonParseException e) {
-                filteredJson = msoResponse;
-            } catch (IOException e) {
-                throw new GenericUncheckedException(e);
-            }
+        final String errorMsg = "Http Code:" + statusCode;
+
+        if (isEmpty(msoResponse)) {
+            return errorMsg;
+        }
+
+        try {
+            JsonNode jsonNode = JACKSON_OBJECT_MAPPER.readTree(msoResponse);
 
-            errorMsg = errorMsg + ", " + filteredJson;
+            return errorMsg + ", " + firstNonBlank(
+                removeBraces(jsonNode.get("serviceException")),
+                removeBraces(jsonNode.path("requestError").get("serviceException")),
+                msoResponse
+            );
+
+        } catch (Exception e) {
+            return errorMsg + ", " + msoResponse;
         }
-        return errorMsg;
+    }
+
+    private static String removeBraces(JsonNode jsonNode) {
+        if (jsonNode == null || jsonNode.isMissingNode()) {
+            return null;
+        }
+
+        return jsonNode.toString().replaceAll("[\\{\\}]", "");
     }
 }
index e610d6c..acbf778 100644 (file)
 
 package org.onap.vid.mso.model;
 
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import org.onap.vid.mso.rest.SubscriberInfo;
-
 import java.util.List;
 import java.util.Map;
-
-import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
-import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+import java.util.Objects;
+import org.onap.vid.mso.rest.SubscriberInfo;
 
 public class ServiceInstantiationRequestDetails {
 
@@ -122,7 +123,11 @@ public class ServiceInstantiationRequestDetails {
         private final String name;
         private final String value;
 
-        public UserParamNameAndValue(String name, String value) {
+        @JsonCreator
+        public UserParamNameAndValue(
+            @JsonProperty("name") String name,
+            @JsonProperty("value") String value
+        ) {
             this.name = name;
             this.value = value;
         }
@@ -134,6 +139,24 @@ public class ServiceInstantiationRequestDetails {
         public String getValue() {
             return value;
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof UserParamNameAndValue)) {
+                return false;
+            }
+            UserParamNameAndValue that = (UserParamNameAndValue) o;
+            return Objects.equals(getName(), that.getName()) &&
+                Objects.equals(getValue(), that.getValue());
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(getName(), getValue());
+        }
     }
 
     public static class HomingSolution implements UserParamTypes {
index bba4081..bf9e41a 100644 (file)
@@ -103,7 +103,7 @@ data class VfModuleOrVolumeGroupRequestDetails(
 
 open class RequestParametersVfModuleOrVolumeGroup internal constructor(
         userParams: List<UserParamTypes>,
-        @get:JsonInclude(NON_NULL) val isUsePreload: Boolean?,
+        val isUsePreload: Boolean,
         testApi: String?
 ) : BaseResourceInstantiationRequestDetails.RequestParameters(userParams, testApi)
 
@@ -111,7 +111,7 @@ class RequestParametersVfModuleOrVolumeGroupInstantiation(
         userParams: List<UserParamTypes>,
         usePreload: Boolean?,
         testApi: String?
-) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload, testApi)
+) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload.orFalse(), testApi)
 
 class RequestParametersVfModuleUpgrade(
         userParams: List<UserParamTypes>,
@@ -119,7 +119,8 @@ class RequestParametersVfModuleUpgrade(
         testApi: String?,
         @get:JsonInclude(NON_NULL) val retainAssignments: Boolean?,
         @get:JsonInclude(NON_NULL) val rebuildVolumeGroups: Boolean?
-) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload, testApi)
+) : RequestParametersVfModuleOrVolumeGroup(userParams, usePreload.orFalse(), testApi)
 
 class UserParamMap<K, V> : HashMap<K, V>(), UserParamTypes, MutableMap<K, V>
 
+private fun Boolean?.orFalse(): Boolean = this ?: false
diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/FeatureSetsManager.kt b/vid-app-common/src/main/java/org/onap/vid/properties/FeatureSetsManager.kt
new file mode 100644 (file)
index 0000000..207bde7
--- /dev/null
@@ -0,0 +1,82 @@
+package org.onap.vid.properties
+
+import org.apache.commons.io.filefilter.WildcardFileFilter
+import org.springframework.web.context.request.RequestContextHolder.getRequestAttributes
+import org.springframework.web.context.request.ServletRequestAttributes
+import org.togglz.core.Feature
+import org.togglz.core.manager.FeatureManager
+import org.togglz.core.manager.FeatureManagerBuilder
+import org.togglz.core.repository.file.FileBasedStateRepository
+import java.io.File
+import java.io.FilenameFilter
+import javax.servlet.ServletContext
+import javax.servlet.http.HttpServletRequest
+
+
+private const val SLOW_RELOAD = 60_000
+private const val COOKIE_NAME = "features.set"
+
+class FeatureSetsManager(
+        private val defaultManager: FeatureManager,
+        private val nameProvider: AlternativeFeatureSetNameProvider,
+        private val servletContext: ServletContext
+) : FeatureManager by defaultManager {
+
+    override fun isActive(feature: Feature?): Boolean {
+        return resolvedFeatureManager().isActive(feature)
+    }
+
+    private fun resolvedFeatureManager(): FeatureManager {
+        return when (val alternativeFeatureSetName = nameProvider.alternativeFeatureSetName) {
+            null -> defaultManager
+            else -> allFeatureManagers.getValue(alternativeFeatureSetName)
+        }
+    }
+
+    internal val allFeatureManagers: Map<String, FeatureManager> by lazy {
+        allFeatureSetFiles().associateBy(
+                { it.name },
+                { newFeatureManager(it) }
+        ).withDefault { allFeaturesOff }
+    }
+
+    private val allFeaturesOff =
+            FeatureManagerBuilder().featureEnum(Features::class.java).build()
+
+    private fun newFeatureManager(file: File): FeatureManager {
+        return FeatureManagerBuilder()
+                .featureEnum(Features::class.java)
+                .stateRepository(FileBasedStateRepository(file, SLOW_RELOAD))
+                .build()
+    }
+
+    private fun allFeatureSetFiles(): Array<File> {
+        val dir = File(servletContext.getRealPath("/WEB-INF/conf/"))
+        val fileFilter: FilenameFilter = WildcardFileFilter("*.features.properties")
+
+        return dir.listFiles(fileFilter) ?: emptyArray()
+    }
+}
+
+interface AlternativeFeatureSetNameProvider {
+    val alternativeFeatureSetName: String?
+}
+
+class AlternativeFeatureSetNameFromCookie: AlternativeFeatureSetNameProvider {
+    override val alternativeFeatureSetName: String?
+        get() = valueFromCookie(currentHttpRequest())
+
+    internal fun valueFromCookie(httpServletRequest: HttpServletRequest?): String? {
+        return httpServletRequest
+                ?.cookies
+                ?.firstOrNull { it.name == COOKIE_NAME }
+                ?.value
+    }
+
+    internal fun currentHttpRequest(): HttpServletRequest? {
+        return when (val requestAttributes = getRequestAttributes()) {
+            is ServletRequestAttributes -> requestAttributes.request
+            else -> null
+        }
+    }
+}
index a421103..cc3fad6 100644 (file)
@@ -81,9 +81,13 @@ public enum Features implements Feature {
     FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND,
     FLAG_2004_INSTANTIATION_STATUS_FILTER,
     FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE,
-    FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER,
     FLAG_2004_INSTANTIATION_TEMPLATES_POPUP,
+    FLAG_2006_VFM_SDNC_PRELOAD_FILES,
     FLAG_2002_UNLIMITED_MAX,
+    FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO,
+    FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY,
+    FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF,
+
     ;
 
 
index 4d4387d..96331b7 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.onap.vid.properties;
 
+import java.io.File;
+import javax.servlet.ServletContext;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.annotation.Bean;
@@ -30,9 +32,6 @@ import org.togglz.core.manager.FeatureManagerBuilder;
 import org.togglz.core.repository.file.FileBasedStateRepository;
 import org.togglz.spring.listener.TogglzApplicationContextBinderApplicationListener;
 
-import javax.servlet.ServletContext;
-import java.io.File;
-
 @Configuration
 public class FeaturesTogglingConfiguration {
     @Bean
@@ -52,11 +51,13 @@ public class FeaturesTogglingConfiguration {
 
         filename = StringUtils.trimToNull(filename);
 
-        return new FeatureManagerBuilder()
+        return new FeatureSetsManager(
+            new FeatureManagerBuilder()
                 .featureEnum(Features.class)
                 .stateRepository(new FileBasedStateRepository(
-                        new File(filename.startsWith("/")? filename : servletContext.getRealPath("/WEB-INF/conf/" + filename))
+                    new File(filename.startsWith("/") ? filename : servletContext.getRealPath("/WEB-INF/conf/" + filename))
                 ))
-                .build();
+                .build(), new AlternativeFeatureSetNameFromCookie(), servletContext
+        );
     }
 }
index 4e5340f..66eab18 100644 (file)
@@ -27,17 +27,17 @@ public class AlwaysValidRoleValidator implements RoleValidator {
     }
 
     @Override
-    public boolean isSubscriberPermitted(String subscriberName) {
+    public boolean isSubscriberPermitted(String subscriberId) {
         return true;
     }
 
     @Override
-    public boolean isServicePermitted(String subscriberName, String serviceType) {
+    public boolean isServicePermitted(WithPermissionProperties permissionProperties) {
         return true;
     }
 
     @Override
-    public boolean isTenantPermitted(String globalCustomerId, String serviceType, String tenantName) {
+    public boolean isTenantPermitted(String subscriberId, String serviceType, String tenantName) {
         return true;
     }
 }
diff --git a/vid-app-common/src/main/java/org/onap/vid/roles/PermissionProperties.kt b/vid-app-common/src/main/java/org/onap/vid/roles/PermissionProperties.kt
new file mode 100644 (file)
index 0000000..dbdd413
--- /dev/null
@@ -0,0 +1,34 @@
+package org.onap.vid.roles
+
+import org.onap.vid.aai.ServiceSubscription
+
+
+interface WithPermissionProperties
+
+interface WithPermissionPropertiesSubscriberAndServiceType: WithPermissionProperties {
+    val subscriberId: String?
+    val serviceType: String?
+}
+
+interface WithPermissionPropertiesOwningEntity: WithPermissionProperties {
+    val owningEntityId: String?
+}
+
+
+data class AllPermissionProperties(
+        override val subscriberId: String?,
+        override val serviceType: String?,
+        override val owningEntityId: String?
+): WithPermissionPropertiesOwningEntity, WithPermissionPropertiesSubscriberAndServiceType
+
+data class PermissionPropertiesOwningEntity(
+        override val owningEntityId: String?
+): WithPermissionPropertiesOwningEntity
+
+data class PermissionPropertiesSubscriberAndServiceType(
+        override val subscriberId: String?,
+        override val serviceType: String?
+) : WithPermissionPropertiesSubscriberAndServiceType {
+    constructor(serviceSubscription: ServiceSubscription, subscriberId: String?) : this(subscriberId, serviceSubscription.serviceType)
+}
+
index 4544830..3de8944 100644 (file)
 
 package org.onap.vid.roles;
 
-/**
- * Created by Oren on 7/1/17.
- */
-
 public class Role {
 
-    private EcompRole ecompRole;
+    private final EcompRole ecompRole;
+
+    private final String subscriberId;
 
-    private String subscribeName;
+    private final String serviceType;
 
-    private String serviceType;
+    private final String tenant;
 
-    private String tenant;
+    private final String owningEntityId;
 
-    public Role(EcompRole ecompRole, String subscribeName, String serviceType, String tenant) {
+    public Role(EcompRole ecompRole, String subscriberId, String serviceType, String tenant, String owningEntityId) {
         this.ecompRole = ecompRole;
-        this.subscribeName = subscribeName;
+        this.subscriberId = subscriberId;
         this.serviceType = serviceType;
         this.tenant = tenant;
+        this.owningEntityId = owningEntityId;
     }
 
     public EcompRole getEcompRole() {
         return ecompRole;
     }
 
-
-    public String getSubscribeName() {
-        return subscribeName;
-    }
-
-    public void setSubscribeName(String subscribeName) {
-        this.subscribeName = subscribeName;
+    public String getSubscriberId() {
+        return subscriberId;
     }
 
     public String getServiceType() {
         return serviceType;
     }
 
-
     public String getTenant() {
         return tenant;
     }
 
-
+    public String getOwningEntityId() {
+        return owningEntityId;
+    }
 
 }
index 898db33..c35f5f7 100644 (file)
@@ -42,11 +42,6 @@ import org.onap.vid.services.AaiService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-
-/**
- * Created by Oren on 7/1/17.
- */
-
 @Component
 public class RoleProvider {
 
@@ -58,16 +53,20 @@ public class RoleProvider {
 
     private Function<HttpServletRequest, Integer> getUserIdFunction;
     private Function<HttpServletRequest, Map> getRolesFunction;
+    private final RoleValidatorFactory roleValidatorFactory;
 
     @Autowired
-    public RoleProvider(AaiService aaiService) {
+    public RoleProvider(AaiService aaiService, RoleValidatorFactory roleValidatorFactory) {
         this.aaiService=aaiService;
+        this.roleValidatorFactory = roleValidatorFactory;
         getUserIdFunction = UserUtils::getUserId;
         getRolesFunction = UserUtils::getRoles;
     }
 
-    RoleProvider(AaiService aaiService, Function<HttpServletRequest, Integer> getUserIdFunction, Function<HttpServletRequest, Map> getRolesFunction) {
+    RoleProvider(AaiService aaiService, RoleValidatorFactory roleValidatorFactory,
+        Function<HttpServletRequest, Integer> getUserIdFunction, Function<HttpServletRequest, Map> getRolesFunction) {
         this.aaiService = aaiService;
+        this.roleValidatorFactory = roleValidatorFactory;
         this.getRolesFunction = getRolesFunction;
         this.getUserIdFunction = getUserIdFunction;
     }
@@ -143,11 +142,13 @@ public class RoleProvider {
 
     public Role createRoleFromStringArr(String[] roleParts, String rolePrefix) throws RoleParsingException {
         String globalCustomerID = replaceSubscriberNameToGlobalCustomerID(roleParts[0], rolePrefix);
+        String owningEntityId = translateOwningEntityNameToOwningEntityId(roleParts[0]);
+
         try {
             if (roleParts.length > 2) {
-                return new Role(EcompRole.READ, globalCustomerID, roleParts[1], roleParts[2]);
+                return new Role(EcompRole.READ, globalCustomerID, roleParts[1], roleParts[2], owningEntityId);
             } else {
-                return new Role(EcompRole.READ, globalCustomerID, roleParts[1], null);
+                return new Role(EcompRole.READ, globalCustomerID, roleParts[1], null, owningEntityId);
             }
         } catch (ArrayIndexOutOfBoundsException e) {
             if (roleParts.length > 0)
@@ -161,8 +162,12 @@ public class RoleProvider {
 
     }
 
+    private String translateOwningEntityNameToOwningEntityId(String owningEntityName) {
+        return owningEntityName; // TODO: translate to id
+    }
+
     public RoleValidator getUserRolesValidator(HttpServletRequest request) {
-        return RoleValidator.by(getUserRoles(request));
+        return roleValidatorFactory.by(getUserRoles(request));
     }
 }
 
index 830c0f5..14c0273 100644 (file)
 
 package org.onap.vid.roles;
 
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.onap.portalsdk.core.util.SystemProperties;
-
 public interface RoleValidator {
 
-    static RoleValidator by(List<Role> roles) {
-        final boolean disableRoles = StringUtils.equals(SystemProperties.getProperty("role_management_activated"), "false");
-        return by(roles, disableRoles);
-    }
-
-    static RoleValidator by(List<Role> roles, boolean disableRoles) {
-        return disableRoles
-            ? new AlwaysValidRoleValidator()
-            : new RoleValidatorByRoles(roles);
-    }
-
-    boolean isSubscriberPermitted(String subscriberName);
+    boolean isSubscriberPermitted(String subscriberId);
 
-    boolean isServicePermitted(String subscriberName, String serviceType);
+    boolean isServicePermitted(WithPermissionProperties serviceInstanceSearchResult);
 
-    boolean isTenantPermitted(String globalCustomerId, String serviceType, String tenantName);
+    boolean isTenantPermitted(String subscriberId, String serviceType, String tenantName);
 }
diff --git a/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorByOwningEntity.java b/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorByOwningEntity.java
new file mode 100644 (file)
index 0000000..8d73dc4
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 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.onap.vid.roles;
+
+
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+
+public class RoleValidatorByOwningEntity implements RoleValidator{
+
+    private final List<Role> userRoles;
+
+    RoleValidatorByOwningEntity(List<Role> roles) {
+        this.userRoles = roles;
+    }
+
+    private boolean isOwningEntityIdPermitted(String owningEntityId) {
+        if (StringUtils.isEmpty(owningEntityId)) {
+            return false;
+        }
+
+        return userRoles.stream().anyMatch(userRole ->
+            StringUtils.equals(userRole.getOwningEntityId(), owningEntityId)
+        );
+    }
+
+    @Override
+    public boolean isSubscriberPermitted(String subscriberId) {
+        return false;
+    }
+
+    @Override
+    public boolean isServicePermitted(WithPermissionProperties permissionProperties) {
+        if (permissionProperties instanceof WithPermissionPropertiesOwningEntity) {
+            String owningEntityId = ((WithPermissionPropertiesOwningEntity) permissionProperties).getOwningEntityId();
+            return isOwningEntityIdPermitted(owningEntityId);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean isTenantPermitted(String subscriberId, String serviceType, String tenantName) {
+        return false;
+    }
+}
 package org.onap.vid.roles;
 
 import java.util.List;
-import java.util.Map;
-import org.onap.vid.mso.rest.RequestDetails;
+import org.apache.commons.lang3.StringUtils;
 
-public class RoleValidatorByRoles implements RoleValidator {
+public class RoleValidatorBySubscriberAndServiceType implements RoleValidator {
 
     private final List<Role> userRoles;
 
-    RoleValidatorByRoles(List<Role> roles) {
+    RoleValidatorBySubscriberAndServiceType(List<Role> roles) {
         this.userRoles = roles;
     }
 
     @Override
-    public boolean isSubscriberPermitted(String subscriberName) {
+    public boolean isSubscriberPermitted(String subscriberId) {
         for (Role role : userRoles) {
-            if (role.getSubscribeName().equals(subscriberName)) {
+            if (role.getSubscriberId().equals(subscriberId)) {
                 return true;
             }
         }
@@ -43,19 +42,26 @@ public class RoleValidatorByRoles implements RoleValidator {
     }
 
     @Override
-    public boolean isServicePermitted(String subscriberName, String serviceType) {
-        for (Role role : userRoles) {
-            if (role.getSubscribeName().equals(subscriberName) && role.getServiceType().equals(serviceType)) {
-                return true;
-            }
+    public boolean isServicePermitted(WithPermissionProperties permissionProperties) {
+        if (permissionProperties instanceof WithPermissionPropertiesSubscriberAndServiceType) {
+            return isServicePermitted(
+                (WithPermissionPropertiesSubscriberAndServiceType) permissionProperties
+            );
         }
         return false;
     }
 
+    private boolean isServicePermitted(WithPermissionPropertiesSubscriberAndServiceType permissionProperties) {
+        return userRoles.stream().anyMatch(userRole ->
+            StringUtils.equals(userRole.getSubscriberId(), permissionProperties.getSubscriberId())
+                && StringUtils.equals(userRole.getServiceType(), permissionProperties.getServiceType())
+        );
+    }
+
     @Override
-    public boolean isTenantPermitted(String globalCustomerId, String serviceType, String tenantName) {
+    public boolean isTenantPermitted(String subscriberId, String serviceType, String tenantName) {
         for (Role role : userRoles) {
-            if (role.getSubscribeName().equals(globalCustomerId)
+            if (role.getSubscriberId().equals(subscriberId)
                 && role.getServiceType().equals(serviceType)
                 && (role.getTenant() == null || role.getTenant().equalsIgnoreCase(tenantName))) {
                 return true;
@@ -64,17 +70,4 @@ public class RoleValidatorByRoles implements RoleValidator {
         return false;
     }
 
-    boolean isMsoRequestValid(RequestDetails msoRequest) {
-        try {
-            String globalSubscriberIdRequested = (String) ((Map) ((Map) msoRequest.getAdditionalProperties()
-                .get("requestDetails")).get("subscriberInfo")).get("globalSubscriberId");
-            String serviceType = (String) ((Map) ((Map) msoRequest.getAdditionalProperties().get("requestDetails"))
-                .get("requestParameters")).get("subscriptionServiceType");
-            return isServicePermitted(globalSubscriberIdRequested, serviceType);
-        } catch (Exception e) {
-            //Until we'll get the exact information regarding the tenants and the global customer id, we'll return true on unknown requests to mso
-            return true;
-        }
-    }
-
 }
diff --git a/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorFactory.java b/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorFactory.java
new file mode 100644 (file)
index 0000000..b171ad7
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2020 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.onap.vid.roles;
+
+
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.portalsdk.core.util.SystemProperties;
+import org.onap.vid.properties.Features;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.togglz.core.manager.FeatureManager;
+
+@Component
+public class RoleValidatorFactory {
+    private final FeatureManager featureManager;
+
+    @Autowired
+    public RoleValidatorFactory(FeatureManager featureManager) {
+        this.featureManager = featureManager;
+    }
+
+
+    public RoleValidator by(List<Role> roles) {
+        final boolean disableRoles = StringUtils
+            .equals(SystemProperties.getProperty("role_management_activated"), "false");
+        return by(roles, disableRoles);
+    }
+
+    public RoleValidator by(List<Role> roles, boolean disableRoles) {
+
+        if(disableRoles) {
+            return new AlwaysValidRoleValidator();
+        }
+        else if (featureManager.isActive(Features.FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY)){
+            return new RoleValidatorsComposer(
+                new RoleValidatorBySubscriberAndServiceType(roles),
+                new RoleValidatorByOwningEntity(roles)
+            );
+        }
+        else {
+            return new RoleValidatorBySubscriberAndServiceType(roles);
+        }
+    }
+}
diff --git a/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorsComposer.kt b/vid-app-common/src/main/java/org/onap/vid/roles/RoleValidatorsComposer.kt
new file mode 100644 (file)
index 0000000..d012cb3
--- /dev/null
@@ -0,0 +1,16 @@
+package org.onap.vid.roles
+
+class RoleValidatorsComposer(private vararg val roleValidators: RoleValidator) : RoleValidator {
+
+    constructor(roleValidators: Collection<RoleValidator>) : this(*roleValidators.toTypedArray())
+
+    override fun isServicePermitted(p: WithPermissionProperties): Boolean =
+            roleValidators.any { it.isServicePermitted(p) }
+
+    override fun isSubscriberPermitted(subscriberId: String?): Boolean =
+            roleValidators.any { it.isSubscriberPermitted(subscriberId) }
+
+    override fun isTenantPermitted(subscriberId: String?, serviceType: String?, tenantName: String?): Boolean =
+            roleValidators.any { it.isTenantPermitted(subscriberId, serviceType, tenantName) }
+
+}
index b3ac168..1e79ab4 100644 (file)
@@ -21,6 +21,8 @@
 
 package org.onap.vid.services;
 
+import static java.util.Collections.emptyList;
+import static org.apache.commons.collections4.ListUtils.emptyIfNull;
 import static org.onap.vid.aai.AaiClient.QUERY_FORMAT_RESOURCE;
 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 
@@ -33,8 +35,10 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
@@ -85,6 +89,7 @@ import org.onap.vid.model.aaiTree.NodeType;
 import org.onap.vid.model.aaiTree.RelatedVnf;
 import org.onap.vid.model.aaiTree.VpnBinding;
 import org.onap.vid.model.aaiTree.VpnBindingKt;
+import org.onap.vid.roles.PermissionPropertiesSubscriberAndServiceType;
 import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.utils.Intersection;
 import org.onap.vid.utils.Logging;
@@ -97,6 +102,7 @@ public class AaiServiceImpl implements AaiService {
     private static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
     private static final String SERVICE_TYPE = "service-subscription.service-type";
     private static final String CUSTOMER_ID = "customer.global-customer-id";
+    private static final String OWNING_ENTITY_ID = "owning-entity.owning-entity-id";
     private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
     private static final String TENANT_NODE_TYPE = "tenant";
     private static final String CLOUD_REGION_NODE_TYPE = "cloud-region";
@@ -167,39 +173,42 @@ public class AaiServiceImpl implements AaiService {
         }
     }
 
-    private List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
+    List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
         AaiResponse<OwningEntityResponse> owningEntityResponse = aaiClient.getServicesByOwningEntityId(owningEntities);
         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
         if (owningEntityResponse.getT() != null) {
             for (OwningEntity owningEntity : owningEntityResponse.getT().getOwningEntity()) {
                 if (owningEntity.getRelationshipList() != null) {
-                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(owningEntity, serviceInstanceSearchResultList, roleValidator);
+                    serviceInstanceSearchResultList.addAll(convertRelationshipToSearchResult(owningEntity, roleValidator, owningEntity.getOwningEntityId()));
                 }
             }
         }
         return serviceInstanceSearchResultList;
     }
 
-    private List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
+    List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
         AaiResponse<ProjectResponse> projectByIdResponse = aaiClient.getServicesByProjectNames(projectNames);
         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
         if (projectByIdResponse.getT() != null) {
             for (Project project : projectByIdResponse.getT().getProject()) {
                 if (project.getRelationshipList() != null) {
-                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(project, serviceInstanceSearchResultList, roleValidator);
+                    serviceInstanceSearchResultList.addAll(convertRelationshipToSearchResult(project, roleValidator, null));
                 }
             }
         }
         return serviceInstanceSearchResultList;
     }
 
-    private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse owningEntityResponse, List<ServiceInstanceSearchResult> serviceInstanceSearchResultList, RoleValidator roleValidator) {
-        if (owningEntityResponse.getRelationshipList().getRelationship() != null) {
-            List<Relationship> relationshipList = owningEntityResponse.getRelationshipList().getRelationship();
+    private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse aaiRelationResponse, RoleValidator roleValidator, String owningEntityId) {
+        List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
+        if (aaiRelationResponse.getRelationshipList().getRelationship() != null) {
+            List<Relationship> relationshipList = aaiRelationResponse.getRelationshipList().getRelationship();
             for (Relationship relationship : relationshipList) {
                 ServiceInstanceSearchResult serviceInstanceSearchResult = new ServiceInstanceSearchResult();
                 extractRelationshipData(relationship, serviceInstanceSearchResult, roleValidator);
                 extractRelatedToProperty(relationship, serviceInstanceSearchResult);
+                serviceInstanceSearchResult.setOwningEntityId(owningEntityId);
+                serviceInstanceSearchResult.setIsPermitted(roleValidator.isServicePermitted(serviceInstanceSearchResult));
                 serviceInstanceSearchResultList.add(serviceInstanceSearchResult);
             }
         }
@@ -217,12 +226,9 @@ public class AaiServiceImpl implements AaiService {
                 } else if (key.equals(SERVICE_TYPE)) {
                     serviceInstanceSearchResult.setServiceType(relationshipData.getRelationshipValue());
                 } else if (key.equals(CUSTOMER_ID)) {
-                    serviceInstanceSearchResult.setGlobalCustomerId(relationshipData.getRelationshipValue());
+                    serviceInstanceSearchResult.setSubscriberId(relationshipData.getRelationshipValue());
                 }
             }
-
-            boolean isPermitted = roleValidator.isServicePermitted(serviceInstanceSearchResult.getSubscriberName(), serviceInstanceSearchResult.getServiceType());
-            serviceInstanceSearchResult.setIsPermitted(isPermitted);
         }
     }
 
@@ -265,10 +271,9 @@ public class AaiServiceImpl implements AaiService {
     @Override
     public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) {
         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances);
-        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
         for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) {
-            String serviceType = serviceSubscription.serviceType;
-            serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
+            serviceSubscription.isPermitted = roleValidator.isServicePermitted(
+                new PermissionPropertiesSubscriberAndServiceType(serviceSubscription, subscriberResponse.getT().globalCustomerId));
         }
         return subscriberResponse;
 
@@ -298,38 +303,45 @@ public class AaiServiceImpl implements AaiService {
 
     private List<ServiceInstanceSearchResult> getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) {
         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, false);
-        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
         String subscriberName = subscriberResponse.getT().subscriberName;
         ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions;
 
-        return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberGlobalId, subscriberName);
-
+        return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberName);
     }
 
 
-    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier, RoleValidator roleValidator, String subscriberGlobalId, String subscriberName) {
+    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(
+        ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier,
+        RoleValidator roleValidator, String subscriberName) {
         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
 
         if (serviceSubscriptions != null) {
             for (ServiceSubscription serviceSubscription : serviceSubscriptions.serviceSubscription) {
-                String serviceType = serviceSubscription.serviceType;
-                serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
-                ArrayList<ServiceInstanceSearchResult> resultsForSubscription = getSearchResultsForSingleSubscription(serviceSubscription, subscriberId, instanceIdentifier, subscriberName, serviceType);
-                results.addAll(resultsForSubscription);
+                serviceSubscription.isPermitted = roleValidator.isServicePermitted(new PermissionPropertiesSubscriberAndServiceType(serviceSubscription, subscriberId));
+                results.addAll(getSearchResultsForSingleSubscription(
+                    serviceSubscription, subscriberId, instanceIdentifier, subscriberName,
+                    serviceSubscription.serviceType, roleValidator)
+                );
             }
         }
 
         return results;
     }
 
-    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName, String serviceType) {
+    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(
+        ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName,
+        String serviceType, RoleValidator roleValidator) {
         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
 
         if (serviceSubscription.serviceInstances != null) {
             for (ServiceInstance serviceInstance : serviceSubscription.serviceInstances.serviceInstance) {
+
                 ServiceInstanceSearchResult serviceInstanceSearchResult =
-                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName,
-                                subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, serviceSubscription.isPermitted);
+                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType,
+                            serviceInstance.serviceInstanceName, subscriberName, serviceInstance.modelInvariantId,
+                            serviceInstance.modelVersionId, relatedOwningEntityId(serviceInstance), false);
+
+                serviceInstanceSearchResult.setIsPermitted(roleValidator.isServicePermitted(serviceInstanceSearchResult));
 
                 if ((instanceIdentifier == null) || (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance))){
                     results.add(serviceInstanceSearchResult);
@@ -340,6 +352,43 @@ public class AaiServiceImpl implements AaiService {
         return results;
     }
 
+    protected String relatedOwningEntityId(ServiceInstance serviceInstance) {
+        /*
+        For reference, consider the service-instance structure below. Method will null-safely extract the
+        `relationship-value` where `relationship-key` == `owning-entity.owning-entity-id`.
+
+        {
+          "service-instance-id": "5d521981-33be-4bb5-bb20-5616a9c52a5a",
+          ...
+          "relationship-list": {
+            "relationship": [
+              {
+                "related-to": "owning-entity",
+                "related-link": "/aai/v11/business/owning-entities/owning-entity/4d4ecf59-41f1-40d4-818d-885234680a42",
+                "relationship-data": [
+                  {
+                    "relationship-key": "owning-entity.owning-entity-id",
+                    "relationship-value": "4d4ecf59-41f1-40d4-818d-885234680a42"
+                  }
+                ]
+              }
+            ]
+          }
+        }
+        */
+
+        Stream<RelationshipData> allRelationships =
+            Optional.ofNullable(serviceInstance.relationshipList)
+                .map(it -> it.getRelationship())
+                .map(it -> it.stream().flatMap(r -> emptyIfNull(r.getRelationDataList()).stream()))
+                .orElse(Stream.empty());
+
+        return allRelationships
+            .filter(r -> StringUtils.equals(r.getRelationshipKey(), OWNING_ENTITY_ID))
+            .map(it -> it.getRelationshipValue())
+            .findAny().orElse(null);
+    }
+
     private boolean serviceInstanceMatchesIdentifier(String instanceIdentifier, ServiceInstance serviceInstance) {
         return instanceIdentifier.equals(serviceInstance.serviceInstanceId) || instanceIdentifier.equals(serviceInstance.serviceInstanceName);
     }
@@ -667,7 +716,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(VpnBindingKt::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }
@@ -683,7 +732,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(Network::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }
index 2cc7649..07c2d15 100644 (file)
@@ -170,7 +170,9 @@ public class AsyncInstantiationBusinessLogicImpl implements
         int bulkSize = request.getBulkSize();
         UUID templateId = UUID.randomUUID();
         for (int i = 0; i < bulkSize; i++) {
-            ServiceInstantiation requestPerJob = prepareServiceToBeUnique(request);
+            ServiceInstantiation clonedServiceInstantiation = cloneServiceInstantiation(request);
+            ServiceInstantiation requestPerJob = prepareServiceToBeUnique(clonedServiceInstantiation);
+            requestPerJob = clearStatusFromRequest(requestPerJob);
             ServiceInfo.ServiceAction serviceAction = getAction(requestPerJob);
             JobType jobType = getJobType(requestPerJob);
             final String optimisticUniqueServiceInstanceName = bulkSize>1 ? //only bulk with more than 1 service need to get multiple names
@@ -561,20 +563,28 @@ public class AsyncInstantiationBusinessLogicImpl implements
 
     @Override
     public ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation) {
+        serviceInstantiation.setBulkSize(1);
+        return replaceAllTrackById(serviceInstantiation);
+    }
+    private<T extends BaseResource> T replaceAllTrackById(T resource) {
+        resource.setTrackById(UUID.randomUUID().toString());
+        resource.getChildren().forEach(this::replaceAllTrackById);
+        return resource;
+    }
+
+    private ServiceInstantiation cloneServiceInstantiation(ServiceInstantiation serviceInstantiation) {
         try {
-            ServiceInstantiation clonedServiceInstantiation = JACKSON_OBJECT_MAPPER.readValue(
-                    JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class);
-            clonedServiceInstantiation.setBulkSize(1);
-            return replaceAllTrackById(clonedServiceInstantiation);
+            return JACKSON_OBJECT_MAPPER.readValue(
+                JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class);
         } catch (IOException e) {
             throw new GenericUncheckedException(e);
         }
-
     }
 
-    private<T extends BaseResource> T replaceAllTrackById(T resource) {
-        resource.setTrackById(UUID.randomUUID().toString());
-        resource.getChildren().forEach(this::replaceAllTrackById);
+    <T extends BaseResource> T clearStatusFromRequest(T resource) {
+        resource.setIsFailed(false);
+        resource.setStatusMessage(null);
+        resource.getChildren().forEach(this::clearStatusFromRequest);
         return resource;
     }
 
index aa00311..17520ee 100644 (file)
@@ -22,28 +22,39 @@ package org.onap.vid.services;
 
 import static java.util.Collections.emptyMap;
 import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toList;
 
+import java.util.Collection;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 import javax.inject.Inject;
+import org.jetbrains.annotations.NotNull;
+import org.onap.vid.asdc.beans.Service;
 import org.onap.vid.dal.AsyncInstantiationRepository;
 import org.onap.vid.model.ModelUtil;
 import org.onap.vid.model.serviceInstantiation.BaseResource;
 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
 import org.onap.vid.model.serviceInstantiation.ServiceInstantiationTemplate;
+import org.onap.vid.properties.Features;
 import org.springframework.stereotype.Component;
+import org.togglz.core.manager.FeatureManager;
 
 @Component
 public class InstantiationTemplatesService {
 
     private final ModelUtil modelUtil;
     private final AsyncInstantiationRepository asyncInstantiationRepository;
+    private FeatureManager featureManager;
+
 
     @Inject
     public InstantiationTemplatesService(ModelUtil modelUtil,
-        AsyncInstantiationRepository asyncInstantiationRepository) {
+        AsyncInstantiationRepository asyncInstantiationRepository,
+        FeatureManager featureManager) {
         this.modelUtil = modelUtil;
         this.asyncInstantiationRepository = asyncInstantiationRepository;
+        this.featureManager = featureManager;
     }
 
     public ServiceInstantiationTemplate getJobRequestAsTemplate(UUID jobId) {
@@ -64,4 +75,25 @@ public class InstantiationTemplatesService {
         );
     }
 
+    public Collection<Service> setOnEachServiceIsTemplateExists(Collection<Service> services){
+        if (!featureManager.isActive(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)){
+            return unsetTemplateExistsToAllServices(services);
+
+        }
+
+        Set<String> serviceModelIdsFromDB  = asyncInstantiationRepository.getAllTemplatesServiceModelIds();
+
+        return services.stream().map(it -> setTemplateExistForService(it, serviceModelIdsFromDB)).collect(toList());
+    }
+
+    @NotNull
+    protected Collection<Service> unsetTemplateExistsToAllServices(Collection<Service> services) {
+        services.forEach(it -> it.setIsInstantiationTemplateExists(false));
+        return services;
+    }
+
+    protected Service setTemplateExistForService(Service service, Set<String> serviceModelIdsFromDb) {
+        service.setIsInstantiationTemplateExists(serviceModelIdsFromDb.contains(service.getUuid()));
+        return service;
+    }
 }
diff --git a/vid-app-common/src/main/java/org/onap/vid/services/UserParamsContainer.kt b/vid-app-common/src/main/java/org/onap/vid/services/UserParamsContainer.kt
new file mode 100644 (file)
index 0000000..17cf88e
--- /dev/null
@@ -0,0 +1,40 @@
+package org.onap.vid.services
+
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue
+import org.onap.vid.mso.model.UserParamTypes
+
+class UserParamsContainer(instanceParams: Map<String, String>?, supplementaryParams: List<UserParamNameAndValue>?) {
+
+    val params:Map<String, String>
+
+    init {
+        params = aggregateAllInstanceParams(instanceParams, supplementaryParams)
+    }
+
+    private fun aggregateAllInstanceParams(
+            instanceParams: Map<String, String>?,
+            supplementaryParams: List<UserParamNameAndValue>?)
+            : Map<String, String> {
+        val instanceParamsSafe: Map<String, String> = instanceParams ?: emptyMap()
+        val supplementaryParamsSafe: Map<String, String> =
+                supplementaryParams?.associate{ it.name to it.value } ?: emptyMap()
+
+        return instanceParamsSafe.plus(supplementaryParamsSafe)
+    }
+
+    fun toALaCarte(): List<UserParamTypes> = toUserParamNameAndValue()
+
+    fun toMacroPre1806() : List<UserParamTypes> = toUserParamNameAndValue()
+
+    fun toMacroPost1806() : List<Map<String, String>> = toListOfMap()
+
+    private fun toUserParamNameAndValue(): List<UserParamNameAndValue> {
+        return params.map{UserParamNameAndValue(it.key, it.value)}.toList()
+    }
+
+    private fun toListOfMap() : List<Map<String, String>> {
+        return listOf(params)
+    }
+}
+
+
index 81afe29..83077f2 100644 (file)
@@ -23,11 +23,15 @@ package org.onap.vid.utils
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
 import org.apache.commons.lang3.StringUtils.isEmpty
+import org.togglz.core.Feature
+import org.togglz.core.manager.FeatureManager
 
 inline fun <reified E: Enum<E>> getEnumFromMapOfStrings(map: Map<String, Any>, key:String, defaultValue:E): E {
     return java.lang.Enum.valueOf(E::class.java, (map.getOrDefault(key, defaultValue.name) as String))
 }
 
+fun FeatureManager.isNotActive(feature: Feature) = this.isActive(feature).not()
+
 @JvmField val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper()
 
 class JoshworksJacksonObjectMapper: io.joshworks.restclient.http.mapper.ObjectMapper {
index 43f059d..f9894d1 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.vid.utils;
 
+import static java.util.Collections.emptyMap;
 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
 import static org.apache.commons.lang3.exception.ExceptionUtils.getRootCause;
 import static org.apache.commons.lang3.exception.ExceptionUtils.getThrowableList;
@@ -220,7 +221,7 @@ public class Logging {
 
     <T> T withMDCInternal(Map<String, String> copyOfParentMDC, UncheckedThrowingSupplier<T> supplier) {
         try {
-            MDC.setContextMap(copyOfParentMDC);
+            MDC.setContextMap(defaultIfNull(copyOfParentMDC, emptyMap()));
             return supplier.get();
         } finally {
             MDC.clear();
index 57427d2..5787a40 100644 (file)
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function d(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function h(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Ot(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function p(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function v(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function S(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function D(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function k(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=D(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&k(e[s])!==k(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function x(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function b(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function H(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function R(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function C(e){var t,n,s={};for(n in e)m(e,n)&&(t=R(n))&&(s[t]=e[n]);return s}var F={};function L(e,t){F[e]=t}function U(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return U(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=x(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=x(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(de(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function de(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var he={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),d(n)&&(s=function(e,t){t[n]=k(e)}),t=0;t<e.length;t++)he[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,pe=4,ve=5,we=6,Me=7,Se=8;function De(e){return ke(e)?366:365}function ke(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),H("year","y"),L("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):k(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return k(e)+(68<k(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(be(this,t,e),c.updateOffset(this,n),this):xe(this,t)}}function xe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function be(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&ke(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?ke(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),H("month","M"),L("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=k(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,He="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var Re="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Ce(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=k(t);else if(!d(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Fe(e){return null!=e?(Ce(this,e),c.updateOffset(this,!0),this):xe(this,"Month")}var Le=ae;var Ue=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=de(s[t]),i[t]=de(i[t]);for(t=0;t<24;t++)r[t]=de(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t=new Date(Date.UTC.apply(null,arguments));return e<100&&0<=e&&isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e),t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return o<=0?a=De(r=e-1)+o:o>De(e)?(r=e+1,a=o-De(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(De(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),H("week","w"),H("isoWeek","W"),L("week",5),L("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=k(e)});I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),H("day","d"),H("weekday","e"),H("isoWeekday","E"),L("day",11),L("weekday",11),L("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=k(e)});var je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var $e=ae;var qe=ae;var Je=ae;function Be(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=de(o[t]),u[t]=de(u[t]),l[t]=de(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function Ke(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Qe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),H("hour","h"),L("hour",13),ue("a",Ke),ue("A",Ke),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=k(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=k(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i))});var et,tt=Te("Hours",!0),nt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:He,monthsShort:Re,week:{dow:0,doy:6},weekdays:je,weekdaysMin:ze,weekdaysShort:Ze,meridiemParse:/[ap]\.?m?\.?/i},st={},it={};function rt(e){return e?e.toLowerCase().replace("_","-"):e}function at(e){var t=null;if(!st[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=et._abbr,require("./locale/"+e),ot(t)}catch(e){}return st[e]}function ot(e,t){var n;return e&&((n=l(t)?lt(e):ut(e,t))?et=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),et._abbr}function ut(e,t){if(null!==t){var n,s=nt;if(t.abbr=e,null!=st[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=st[e]._config;else if(null!=t.parentLocale)if(null!=st[t.parentLocale])s=st[t.parentLocale]._config;else{if(null==(n=at(t.parentLocale)))return it[t.parentLocale]||(it[t.parentLocale]=[]),it[t.parentLocale].push({name:e,config:t}),null;s=n._config}return st[e]=new P(b(s,t)),it[e]&&it[e].forEach(function(e){ut(e.name,e.config)}),ot(e),st[e]}return delete st[e],null}function lt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return et;if(!o(e)){if(t=at(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=rt(e[r]).split("-")).length,n=(n=rt(e[r+1]))?n.split("-"):null;0<t;){if(s=at(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return et}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[pe]||0!==n[ve]||0!==n[we])?ge:n[pe]<0||59<n[pe]?pe:n[ve]<0||59<n[ve]?ve:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=Se),g(e).overflow=t),e}function ht(e,t,n){return null!=e?e:null!=t?t:n}function ct(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ht(t.GG,e._a[me],Ie(Tt(),1,4).year),s=ht(t.W,1),((i=ht(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(Tt(),r,a);n=ht(t.gg,e._a[me],l.year),s=ht(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ht(e._a[me],s[me]),(e._dayOfYear>De(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[pe]&&0===e._a[ve]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&0<=e&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var ft=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,mt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/Z|[+-]\d\d(?::?\d\d)?/,yt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],gt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function vt(e){var t,n,s,i,r,a,o=e._i,u=ft.exec(o)||mt.exec(o);if(u){for(g(e).iso=!0,t=0,n=yt.length;t<n;t++)if(yt[t][1].exec(u[1])){i=yt[t][0],s=!1!==yt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[3])){r=(u[2]||" ")+gt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!_t.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),kt(e)}else e._isValid=!1}var wt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function Mt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),Re.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=wt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim());if(i){var r=Mt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&Ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function kt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,d=l.length,h=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),h+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(he,a)&&he[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=d-h,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ct(e),dt(e)}else Dt(e);else vt(e)}function Yt(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||lt(e._l),null===r||void 0===a&&""===r?v({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),S(r)?new M(dt(r)):(h(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],kt(t),p(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?kt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):h(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(vt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ct(t)):u(n)?function(e){if(!e._d){var t=C(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ct(e)}}(t):d(n)?t._d=new Date(n):c.createFromInputFallback(t),p(e)||(e._d=null),e))}function Ot(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Yt(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function Tt(e,t,n,s){return Ot(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:v()}),bt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=Tt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:v()});function Pt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return Tt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Wt=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=C(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,d=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Wt,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Wt.length;++s)if(e[Wt[s]]){if(n)return!1;parseFloat(e[Wt[s]])!==k(e[Wt[s]])&&(n=!0)}return!0}(t),this._milliseconds=+d+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=lt(),this._bubble()}function Rt(e){return e instanceof Ht}function Ct(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+U(~~(e/60),2)+n+U(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Ut(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Ut(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+k(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Nt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(S(e)||h(e)?e.valueOf():Tt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):Tt(e).local()}function Gt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Vt(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var Et=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,It=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function At(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:d(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=Et.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:k(a[ye])*n,h:k(a[ge])*n,m:k(a[pe])*n,s:k(a[ve])*n,ms:k(Ct(1e3*a[we]))*n}):(a=It.exec(e))?(n="-"===a[1]?-1:(a[1],1),r={y:jt(a[2],n),M:jt(a[3],n),w:jt(a[4],n),d:jt(a[5],n),h:jt(a[6],n),m:jt(a[7],n),s:jt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Nt(t,e),e.isBefore(t)?n=Zt(e,t):((n=Zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(Tt(r.from),Tt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function jt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Zt(e,t){var n={milliseconds:0,months:0};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function zt(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),$t(this,At(e="string"==typeof e?+e:e,t),s),this}}function $t(e,t,n,s){var i=t._milliseconds,r=Ct(t._days),a=Ct(t._months);e.isValid()&&(s=null==s||s,a&&Ce(e,xe(e,"Month")+a*n),r&&be(e,"Date",xe(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}At.fn=Ht.prototype,At.invalid=function(){return At(NaN)};var qt=zt(1,"add"),Jt=zt(-1,"subtract");function Bt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Qt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=lt(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function Kt(){return this._locale}function en(e,t){I(0,[e,e.length],0,t)}function tn(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),en("gggg","weekYear"),en("ggggg","weekYear"),en("GGGG","isoWeekYear"),en("GGGGG","isoWeekYear"),H("weekYear","gg"),H("isoWeekYear","GG"),L("weekYear",1),L("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=k(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),H("quarter","Q"),L("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(k(e)-1)}),I("D",["DD",2],"Do","date"),H("date","D"),L("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=k(e.match(B)[0])});var nn=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),H("dayOfYear","DDD"),L("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=k(e)}),I("m",["mm",2],0,"minute"),H("minute","m"),L("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],pe);var sn=Te("Minutes",!1);I("s",["ss",2],0,"second"),H("second","s"),L("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],ve);var rn,an=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),H("millisecond","ms"),L("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),rn="SSSS";rn.length<=9;rn+="S")ue(rn,ne);function on(e,t){t[we]=k(1e3*("0."+e))}for(rn="S";rn.length<=9;rn+="S")ce(rn,on);var un=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var ln=M.prototype;function dn(e){return e}ln.add=qt,ln.calendar=function(e,t){var n=e||Tt(),s=Nt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(x(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,Tt(n)))},ln.clone=function(){return new M(this)},ln.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Nt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=R(t)){case"year":r=Bt(this,s)/12;break;case"month":r=Bt(this,s);break;case"quarter":r=Bt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:D(r)},ln.endOf=function(e){return void 0===(e=R(e))||"millisecond"===e?this:("date"===e&&(e="day"),this.startOf(e).add(1,"isoWeek"===e?"week":e).subtract(1,"ms"))},ln.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},ln.from=function(e,t){return this.isValid()&&(S(e)&&e.isValid()||Tt(e).isValid())?At({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.fromNow=function(e){return this.from(Tt(),e)},ln.to=function(e,t){return this.isValid()&&(S(e)&&e.isValid()||Tt(e).isValid())?At({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},ln.toNow=function(e){return this.to(Tt(),e)},ln.get=function(e){return x(this[e=R(e)])?this[e]():this},ln.invalidAt=function(){return g(this).overflow},ln.isAfter=function(e,t){var n=S(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(l(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},ln.isBefore=function(e,t){var n=S(e)?e:Tt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=R(l(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},ln.isBetween=function(e,t,n,s){return("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n))},ln.isSame=function(e,t){var n,s=S(e)?e:Tt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=R(t||"millisecond"))?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},ln.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},ln.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},ln.isValid=function(){return p(this)},ln.lang=Xt,ln.locale=Qt,ln.localeData=Kt,ln.max=bt,ln.min=xt,ln.parsingFlags=function(){return _({},g(this))},ln.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:F[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=C(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(x(this[e=R(e)]))return this[e](t);return this},ln.startOf=function(e){switch(e=R(e)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===e&&this.weekday(0),"isoWeek"===e&&this.isoWeekday(1),"quarter"===e&&this.month(3*Math.floor(this.month()/3)),this},ln.subtract=Jt,ln.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},ln.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},ln.toDate=function(){return new Date(this.valueOf())},ln.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):x(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},ln.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},ln.toJSON=function(){return this.isValid()?this.toISOString():null},ln.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ln.unix=function(){return Math.floor(this.valueOf()/1e3)},ln.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ln.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ln.year=Oe,ln.isLeapYear=function(){return ke(this.year())},ln.weekYear=function(e){return tn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ln.isoWeekYear=function(e){return tn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},ln.quarter=ln.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},ln.month=Fe,ln.daysInMonth=function(){return Pe(this.year(),this.month())},ln.week=ln.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},ln.isoWeek=ln.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},ln.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},ln.isoWeeksInYear=function(){return Ae(this.year(),1,4)},ln.date=nn,ln.day=ln.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},ln.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},ln.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=(n=e,s=this.localeData(),"string"==typeof n?s.weekdaysParse(n)%7||7:isNaN(n)?null:n);return this.day(this.day()%7?t:t-7)}return this.day()||7;var n,s},ln.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},ln.hour=ln.hours=tt,ln.minute=ln.minutes=sn,ln.second=ln.seconds=an,ln.millisecond=ln.milliseconds=un,ln.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null!=e){if("string"==typeof e){if(null===(e=Ut(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Gt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?$t(this,At(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?i:Gt(this)},ln.utc=function(e){return this.utcOffset(0,e)},ln.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Gt(this),"m")),this},ln.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Ut(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},ln.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?Tt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},ln.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ln.isLocal=function(){return!!this.isValid()&&!this._isUTC},ln.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ln.isUtc=Vt,ln.isUTC=Vt,ln.zoneAbbr=function(){return this._isUTC?"UTC":""},ln.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ln.dates=n("dates accessor is deprecated. Use date instead.",nn),ln.months=n("months accessor is deprecated. Use month instead",Fe),ln.years=n("years accessor is deprecated. Use year instead",Oe),ln.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),ln.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Yt(e))._a){var t=e._isUTC?y(e._a):Tt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var hn=P.prototype;function cn(e,t,n,s){var i=lt(),r=y().set(s,t);return i[n](r,e)}function fn(e,t,n){if(d(e)&&(t=e,e=void 0),e=e||"",null!=t)return cn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=cn(e,s,n,"month");return i}function mn(e,t,n,s){"boolean"==typeof e?d(t)&&(n=t,t=void 0):(t=e,e=!1,d(n=t)&&(n=t,t=void 0)),t=t||"";var i,r=lt(),a=e?r._week.dow:0;if(null!=n)return cn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=cn(t,(i+a)%7,s,"day");return o}hn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return x(s)?s.call(t,n):s},hn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},hn.invalidDate=function(){return this._invalidDate},hn.ordinal=function(e){return this._ordinal.replace("%d",e)},hn.preparse=dn,hn.postformat=dn,hn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return x(i)?i(e,t,n,s):i.replace(/%d/i,e)},hn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return x(n)?n(t):n.replace(/%s/i,t)},hn.set=function(e){var t,n;for(n in e)x(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},hn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},hn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},hn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},hn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Ue),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},hn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Le),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},hn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},hn.firstDayOfYear=function(){return this._week.doy},hn.firstDayOfWeek=function(){return this._week.dow},hn.weekdays=function(e,t){return e?o(this._weekdays)?this._weekdays[e.day()]:this._weekdays[this._weekdays.isFormat.test(t)?"format":"standalone"][e.day()]:o(this._weekdays)?this._weekdays:this._weekdays.standalone},hn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},hn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},hn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".",".?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},hn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=$e),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},hn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},hn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Be.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Je),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},hn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},hn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ot("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===k(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ot),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",lt);var _n=Math.abs;function yn(e,t,n,s){var i=At(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function gn(e){return e<0?Math.floor(e):Math.ceil(e)}function pn(e){return 4800*e/146097}function vn(e){return 146097*e/4800}function wn(e){return function(){return this.as(e)}}var Mn=wn("ms"),Sn=wn("s"),Dn=wn("m"),kn=wn("h"),Yn=wn("d"),On=wn("w"),Tn=wn("M"),xn=wn("y");function bn(e){return function(){return this.isValid()?this._data[e]:NaN}}var Pn=bn("milliseconds"),Wn=bn("seconds"),Hn=bn("minutes"),Rn=bn("hours"),Cn=bn("days"),Fn=bn("months"),Ln=bn("years");var Un=Math.round,Nn={ss:44,s:45,m:45,h:22,d:26,M:11};var Gn=Math.abs;function Vn(e){return(0<e)-(e<0)||+e}function En(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Gn(this._milliseconds)/1e3,s=Gn(this._days),i=Gn(this._months);t=D((e=D(n/60))/60),n%=60,e%=60;var r=D(i/12),a=i%=12,o=s,u=t,l=e,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Vn(this._months)!==Vn(h)?"-":"",m=Vn(this._days)!==Vn(h)?"-":"",_=Vn(this._milliseconds)!==Vn(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var In=Ht.prototype;return In.isValid=function(){return this._isValid},In.abs=function(){var e=this._data;return this._milliseconds=_n(this._milliseconds),this._days=_n(this._days),this._months=_n(this._months),e.milliseconds=_n(e.milliseconds),e.seconds=_n(e.seconds),e.minutes=_n(e.minutes),e.hours=_n(e.hours),e.months=_n(e.months),e.years=_n(e.years),this},In.add=function(e,t){return yn(this,e,t,1)},In.subtract=function(e,t){return yn(this,e,t,-1)},In.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=R(e))||"year"===e)return t=this._days+s/864e5,n=this._months+pn(t),"month"===e?n:n/12;switch(t=this._days+Math.round(vn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},In.asMilliseconds=Mn,In.asSeconds=Sn,In.asMinutes=Dn,In.asHours=kn,In.asDays=Yn,In.asWeeks=On,In.asMonths=Tn,In.asYears=xn,In.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*k(this._months/12):NaN},In._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*gn(vn(o)+a),o=a=0),u.milliseconds=r%1e3,e=D(r/1e3),u.seconds=e%60,t=D(e/60),u.minutes=t%60,n=D(t/60),u.hours=n%24,o+=i=D(pn(a+=D(n/24))),a-=gn(vn(i)),s=D(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},In.clone=function(){return At(this)},In.get=function(e){return e=R(e),this.isValid()?this[e+"s"]():NaN},In.milliseconds=Pn,In.seconds=Wn,In.minutes=Hn,In.hours=Rn,In.days=Cn,In.weeks=function(){return D(this.days()/7)},In.months=Fn,In.years=Ln,In.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,d,h,c=this.localeData(),f=(n=!e,s=c,i=At(t=this).abs(),r=Un(i.as("s")),a=Un(i.as("m")),o=Un(i.as("h")),u=Un(i.as("d")),l=Un(i.as("M")),d=Un(i.as("y")),(h=r<=Nn.ss&&["s",r]||r<Nn.s&&["ss",r]||a<=1&&["m"]||a<Nn.m&&["mm",a]||o<=1&&["h"]||o<Nn.h&&["hh",o]||u<=1&&["d"]||u<Nn.d&&["dd",u]||l<=1&&["M"]||l<Nn.M&&["MM",l]||d<=1&&["y"]||["yy",d])[2]=n,h[3]=0<+t,h[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,h));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},In.toISOString=En,In.toString=En,In.toJSON=En,In.locale=Qt,In.localeData=Kt,In.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",En),In.lang=Xt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(k(e))}),c.version="2.22.1",e=Tt,c.fn=ln,c.min=function(){return Pt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Pt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return Tt(1e3*e)},c.months=function(e,t){return fn(e,t,"months")},c.isDate=h,c.locale=ot,c.invalid=v,c.duration=At,c.isMoment=S,c.weekdays=function(e,t,n){return mn(e,t,n,"weekdays")},c.parseZone=function(){return Tt.apply(null,arguments).parseZone()},c.localeData=lt,c.isDuration=Rt,c.monthsShort=function(e,t){return fn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return mn(e,t,n,"weekdaysMin")},c.defineLocale=ut,c.updateLocale=function(e,t){if(null!=t){var n,s,i=nt;null!=(s=at(e))&&(i=s._config),(n=new P(t=b(i,t))).parentLocale=st[e],st[e]=n,ot(e)}else null!=st[e]&&(null!=st[e].parentLocale?st[e]=st[e].parentLocale:null!=st[e]&&delete st[e]);return st[e]},c.locales=function(){return s(st)},c.weekdaysShort=function(e,t,n){return mn(e,t,n,"weekdaysShort")},c.normalizeUnits=R,c.relativeTimeRounding=function(e){return void 0===e?Un:"function"==typeof e&&(Un=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==Nn[e]&&(void 0===t?Nn[e]:(Nn[e]=t,"s"===e&&(Nn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=ln,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"YYYY-[W]WW",MONTH:"YYYY-MM"},c});
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Tt(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function v(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function p(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function k(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function S(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function D(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=S(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&D(e[s])!==D(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function b(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function x(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function C(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function H(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function R(e){var t,n,s={};for(n in e)m(e,n)&&(t=H(n))&&(s[t]=e[n]);return s}var U={};function F(e,t){U[e]=t}function L(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return L(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=b(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=b(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(he(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function he(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var de={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),h(n)&&(s=function(e,t){t[n]=D(e)}),t=0;t<e.length;t++)de[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,ve=4,pe=5,we=6,Me=7,ke=8;function Se(e){return De(e)?366:365}function De(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),C("year","y"),F("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):D(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return D(e)+(68<D(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(xe(this,t,e),c.updateOffset(this,n),this):be(this,t)}}function be(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&De(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?De(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),C("month","M"),F("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=D(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var He="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Re(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=D(t);else if(!h(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Ue(e){return null!=e?(Re(this,e),c.updateOffset(this,!0),this):be(this,"Month")}var Fe=ae;var Le=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=he(s[t]),i[t]=he(i[t]);for(t=0;t<24;t++)r[t]=he(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t;if(e<100&&0<=e){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return a=o<=0?Se(r=e-1)+o:o>Se(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=at(e[r]).split("-")).length,n=(n=at(e[r+1]))?n.split("-"):null;0<t;){if(s=ot(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[ve]||0!==n[pe]||0!==n[we])?ge:n[ve]<0||59<n[ve]?ve:n[pe]<0||59<n[pe]?pe:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=ke),g(e).overflow=t),e}function ct(e,t,n){return null!=e?e:null!=t?t:n}function ft(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ct(t.GG,e._a[me],Ie(bt(),1,4).year),s=ct(t.W,1),((i=ct(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(bt(),r,a);n=ct(t.gg,e._a[me],l.year),s=ct(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[1])){i=gt[t][0],s=!1!==gt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=vt.length;t<n;t++)if(vt[t][1].exec(u[3])){r=(u[2]||" ")+vt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!yt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Yt(e)}else e._isValid=!1}var Mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function kt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),He.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=Mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=kt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function Yt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,h=l.length,d=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),d+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(de,a)&&de[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=h-d,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ft(e),dt(e)}else Dt(e);else wt(e)}function Ot(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||ht(e._l),null===r||void 0===a&&""===r?p({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),k(r)?new M(dt(r)):(d(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Yt(t),v(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?Yt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):d(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(wt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ft(t)):u(n)?function(e){if(!e._d){var t=R(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ft(e)}}(t):h(n)?t._d=new Date(n):c.createFromInputFallback(t),v(e)||(e._d=null),e))}function Tt(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Ot(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function bt(e,t,n,s){return Tt(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:p()}),Pt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:p()});function Wt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return bt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Ct=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=R(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||t.isoWeek||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,h=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Ct,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Ct.length;++s)if(e[Ct[s]]){if(n)return!1;parseFloat(e[Ct[s]])!==D(e[Ct[s]])&&(n=!0)}return!0}(t),this._milliseconds=+h+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ht(),this._bubble()}function Rt(e){return e instanceof Ht}function Ut(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+L(~~(e/60),2)+n+L(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Nt(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Nt(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+D(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Gt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(k(e)||d(e)?e.valueOf():bt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):bt(e).local()}function Vt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Et(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var It=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,At=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function jt(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:h(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=It.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:D(a[ye])*n,h:D(a[ge])*n,m:D(a[ve])*n,s:D(a[pe])*n,ms:D(Ut(1e3*a[we]))*n}):(a=At.exec(e))?(n="-"===a[1]?-1:1,r={y:Zt(a[2],n),M:Zt(a[3],n),w:Zt(a[4],n),d:Zt(a[5],n),h:Zt(a[6],n),m:Zt(a[7],n),s:Zt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(bt(r.from),bt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function Zt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,jt(e="string"==typeof e?+e:e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ut(t._days),a=Ut(t._months);e.isValid()&&(s=null==s||s,a&&Re(e,be(e,"Month")+a*n),r&&xe(e,"Date",be(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}jt.fn=Ht.prototype,jt.invalid=function(){return jt(NaN)};var Jt=$t(1,"add"),Bt=$t(-1,"subtract");function Qt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Xt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ht(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Kt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function en(){return this._locale}var tn=126227808e5;function nn(e,t){return(e%t+t)%t}function sn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-tn:new Date(e,t,n).valueOf()}function rn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-tn:Date.UTC(e,t,n)}function an(e,t){I(0,[e,e.length],0,t)}function on(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),C("weekYear","gg"),C("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=D(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),C("quarter","Q"),F("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(D(e)-1)}),I("D",["DD",2],"Do","date"),C("date","D"),F("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=D(e.match(B)[0])});var un=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),C("dayOfYear","DDD"),F("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=D(e)}),I("m",["mm",2],0,"minute"),C("minute","m"),F("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],ve);var ln=Te("Minutes",!1);I("s",["ss",2],0,"second"),C("second","s"),F("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],pe);var hn,dn=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),C("millisecond","ms"),F("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),hn="SSSS";hn.length<=9;hn+="S")ue(hn,ne);function cn(e,t){t[we]=D(1e3*("0."+e))}for(hn="S";hn.length<=9;hn+="S")ce(hn,cn);var fn=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var mn=M.prototype;function _n(e){return e}mn.add=Jt,mn.calendar=function(e,t){var n=e||bt(),s=Gt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(b(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,bt(n)))},mn.clone=function(){return new M(this)},mn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=H(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:S(r)},mn.endOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-nn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-nn(t,1e3)-1;break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},mn.from=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.fromNow=function(e){return this.from(bt(),e)},mn.to=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.toNow=function(e){return this.to(bt(),e)},mn.get=function(e){return b(this[e=H(e)])?this[e]():this},mn.invalidAt=function(){return g(this).overflow},mn.isAfter=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},mn.isBefore=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},mn.isBetween=function(e,t,n,s){var i=k(e)?e:bt(e),r=k(t)?t:bt(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n))},mn.isSame=function(e,t){var n,s=k(e)?e:bt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},mn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},mn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},mn.isValid=function(){return v(this)},mn.lang=Kt,mn.locale=Xt,mn.localeData=en,mn.max=Pt,mn.min=xt,mn.parsingFlags=function(){return _({},g(this))},mn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:U[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=R(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(b(this[e=H(e)]))return this[e](t);return this},mn.startOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=nn(t,6e4);break;case"second":t=this._d.valueOf(),t-=nn(t,1e3);break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.subtract=Bt,mn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},mn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):b(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Oe,mn.isLeapYear=function(){return De(this.year())},mn.weekYear=function(e){return on.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(e){return on.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},mn.month=Ue,mn.daysInMonth=function(){return Pe(this.year(),this.month())},mn.week=mn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},mn.isoWeek=mn.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},mn.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},mn.isoWeeksInYear=function(){return Ae(this.year(),1,4)},mn.date=un,mn.day=mn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},mn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},mn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null==e)return this.day()||7;var t,n,s=(t=e,n=this.localeData(),"string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t);return this.day(this.day()%7?s:s-7)},mn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},mn.hour=mn.hours=nt,mn.minute=mn.minutes=ln,mn.second=mn.seconds=dn,mn.millisecond=mn.milliseconds=fn,mn.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Vt(this);if("string"==typeof e){if(null===(e=Nt(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Vt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,jt(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this},mn.utc=function(e){return this.utcOffset(0,e)},mn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Vt(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Nt(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?bt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var yn=P.prototype;function gn(e,t,n,s){var i=ht(),r=y().set(s,t);return i[n](r,e)}function vn(e,t,n){if(h(e)&&(t=e,e=void 0),e=e||"",null!=t)return gn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=gn(e,s,n,"month");return i}function pn(e,t,n,s){t=("boolean"==typeof e?h(t)&&(n=t,t=void 0):(t=e,e=!1,h(n=t)&&(n=t,t=void 0)),t||"");var i,r=ht(),a=e?r._week.dow:0;if(null!=n)return gn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=gn(t,(i+a)%7,s,"day");return o}yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return b(s)?s.call(t,n):s},yn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},yn.invalidDate=function(){return this._invalidDate},yn.ordinal=function(e){return this._ordinal.replace("%d",e)},yn.preparse=_n,yn.postformat=_n,yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return b(i)?i(e,t,n,s):i.replace(/%d/i,e)},yn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return b(n)?n(t):n.replace(/%s/i,t)},yn.set=function(e){var t,n;for(n in e)b(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},yn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},yn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},yn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},yn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},yn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},yn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},yn.firstDayOfYear=function(){return this._week.doy},yn.firstDayOfWeek=function(){return this._week.dow},yn.weekdays=function(e,t){var n=o(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?je(n,this._week.dow):e?n[e.day()]:n},yn.weekdaysMin=function(e){return!0===e?je(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},yn.weekdaysShort=function(e){return!0===e?je(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},yn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=qe),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Be),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},yn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ut("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===D(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ut),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",ht);var wn=Math.abs;function Mn(e,t,n,s){var i=jt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function kn(e){return e<0?Math.floor(e):Math.ceil(e)}function Sn(e){return 4800*e/146097}function Dn(e){return 146097*e/4800}function Yn(e){return function(){return this.as(e)}}var On=Yn("ms"),Tn=Yn("s"),bn=Yn("m"),xn=Yn("h"),Pn=Yn("d"),Wn=Yn("w"),Cn=Yn("M"),Hn=Yn("Q"),Rn=Yn("y");function Un(e){return function(){return this.isValid()?this._data[e]:NaN}}var Fn=Un("milliseconds"),Ln=Un("seconds"),Nn=Un("minutes"),Gn=Un("hours"),Vn=Un("days"),En=Un("months"),In=Un("years");var An=Math.round,jn={ss:44,s:45,m:45,h:22,d:26,M:11};var Zn=Math.abs;function zn(e){return(0<e)-(e<0)||+e}function $n(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Zn(this._milliseconds)/1e3,s=Zn(this._days),i=Zn(this._months);t=S((e=S(n/60))/60),n%=60,e%=60;var r=S(i/12),a=i%=12,o=s,u=t,l=e,h=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var c=d<0?"-":"",f=zn(this._months)!==zn(d)?"-":"",m=zn(this._days)!==zn(d)?"-":"",_=zn(this._milliseconds)!==zn(d)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||h?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(h?_+h+"S":"")}var qn=Ht.prototype;return qn.isValid=function(){return this._isValid},qn.abs=function(){var e=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),e.milliseconds=wn(e.milliseconds),e.seconds=wn(e.seconds),e.minutes=wn(e.minutes),e.hours=wn(e.hours),e.months=wn(e.months),e.years=wn(e.years),this},qn.add=function(e,t){return Mn(this,e,t,1)},qn.subtract=function(e,t){return Mn(this,e,t,-1)},qn.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=H(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+Sn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Dn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},qn.asMilliseconds=On,qn.asSeconds=Tn,qn.asMinutes=bn,qn.asHours=xn,qn.asDays=Pn,qn.asWeeks=Wn,qn.asMonths=Cn,qn.asQuarters=Hn,qn.asYears=Rn,qn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},qn._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*kn(Dn(o)+a),o=a=0),u.milliseconds=r%1e3,e=S(r/1e3),u.seconds=e%60,t=S(e/60),u.minutes=t%60,n=S(t/60),u.hours=n%24,o+=i=S(Sn(a+=S(n/24))),a-=kn(Dn(i)),s=S(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},qn.clone=function(){return jt(this)},qn.get=function(e){return e=H(e),this.isValid()?this[e+"s"]():NaN},qn.milliseconds=Fn,qn.seconds=Ln,qn.minutes=Nn,qn.hours=Gn,qn.days=Vn,qn.weeks=function(){return S(this.days()/7)},qn.months=En,qn.years=In,qn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,h,d,c=this.localeData(),f=(n=!e,s=c,i=jt(t=this).abs(),r=An(i.as("s")),a=An(i.as("m")),o=An(i.as("h")),u=An(i.as("d")),l=An(i.as("M")),h=An(i.as("y")),(d=r<=jn.ss&&["s",r]||r<jn.s&&["ss",r]||a<=1&&["m"]||a<jn.m&&["mm",a]||o<=1&&["h"]||o<jn.h&&["hh",o]||u<=1&&["d"]||u<jn.d&&["dd",u]||l<=1&&["M"]||l<jn.M&&["MM",l]||h<=1&&["y"]||["yy",h])[2]=n,d[3]=0<+t,d[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},qn.toISOString=$n,qn.toString=$n,qn.toJSON=$n,qn.locale=Xt,qn.localeData=en,qn.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$n),qn.lang=Kt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(D(e))}),c.version="2.24.0",e=bt,c.fn=mn,c.min=function(){return Wt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Wt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return bt(1e3*e)},c.months=function(e,t){return vn(e,t,"months")},c.isDate=d,c.locale=ut,c.invalid=p,c.duration=jt,c.isMoment=k,c.weekdays=function(e,t,n){return pn(e,t,n,"weekdays")},c.parseZone=function(){return bt.apply(null,arguments).parseZone()},c.localeData=ht,c.isDuration=Rt,c.monthsShort=function(e,t){return vn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return pn(e,t,n,"weekdaysMin")},c.defineLocale=lt,c.updateLocale=function(e,t){if(null!=t){var n,s,i=st;null!=(s=ot(e))&&(i=s._config),(n=new P(t=x(i,t))).parentLocale=it[e],it[e]=n,ut(e)}else null!=it[e]&&(null!=it[e].parentLocale?it[e]=it[e].parentLocale:null!=it[e]&&delete it[e]);return it[e]},c.locales=function(){return s(it)},c.weekdaysShort=function(e,t,n){return pn(e,t,n,"weekdaysShort")},c.normalizeUnits=H,c.relativeTimeRounding=function(e){return void 0===e?An:"function"==typeof e&&(An=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==jn[e]&&(void 0===t?jn[e]:(jn[e]=t,"s"===e&&(jn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=mn,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},c});
\ No newline at end of file
index c911263..13ec307 100644 (file)
 return true}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function o(n,t){return!(null==n||!n.length)&&-1<v(n,t,0)}function f(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return true;return false}function c(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function a(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function l(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);
 return r}function s(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function h(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return true;return false}function p(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,false}),e}function _(n,t,r,e){var u=n.length;for(r+=e?1:-1;e?r--:++r<u;)if(t(n[r],r,n))return r;return-1}function v(n,t,r){if(t===t)n:{--r;for(var e=n.length;++r<e;)if(n[r]===t){n=r;break n}n=-1}else n=_(n,d,r);return n}function g(n,t,r,e){
 --r;for(var u=n.length;++r<u;)if(e(n[r],t))return r;return-1}function d(n){return n!==n}function y(n,t){var r=null==n?0:n.length;return r?m(n,t)/r:F}function b(n){return function(t){return null==t?T:t[n]}}function x(n){return function(t){return null==n?T:n[t]}}function j(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=false,n):t(r,n,u,i)}),r}function w(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function m(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==T&&(r=r===T?i:r+i)}return r;
-}function A(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function k(n,t){return c(t,function(t){return[t,n[t]]})}function E(n){return function(t){return n(t)}}function S(n,t){return c(t,function(t){return n[t]})}function O(n,t){return n.has(t)}function I(n,t){for(var r=-1,e=n.length;++r<e&&-1<v(t,n[r],0););return r}function R(n,t){for(var r=n.length;r--&&-1<v(t,n[r],0););return r}function z(n){return"\\"+Ln[n]}function W(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n];
-}),r}function U(n,t){return function(r){return n(t(r))}}function B(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function L(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function C(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function D(n){if(Rn.test(n)){for(var t=On.lastIndex=0;On.test(n);)++t;n=t}else n=Qn(n);return n}function M(n){return Rn.test(n)?n.match(On)||[]:n.split("");
-}var T,$=1/0,F=NaN,N=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],P=/\b__p\+='';/g,Z=/\b(__p\+=)''\+/g,q=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\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])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,kn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",En=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+kn+mn,"g"),In=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|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="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(" "),Un={};
-Un["[object Float32Array]"]=Un["[object Float64Array]"]=Un["[object Int8Array]"]=Un["[object Int16Array]"]=Un["[object Int32Array]"]=Un["[object Uint8Array]"]=Un["[object Uint8ClampedArray]"]=Un["[object Uint16Array]"]=Un["[object Uint32Array]"]=true,Un["[object Arguments]"]=Un["[object Array]"]=Un["[object ArrayBuffer]"]=Un["[object Boolean]"]=Un["[object DataView]"]=Un["[object Date]"]=Un["[object Error]"]=Un["[object Function]"]=Un["[object Map]"]=Un["[object Number]"]=Un["[object Object]"]=Un["[object RegExp]"]=Un["[object Set]"]=Un["[object String]"]=Un["[object WeakMap]"]=false;
-var Bn={};Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object DataView]"]=Bn["[object Boolean]"]=Bn["[object Date]"]=Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object Symbol]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,
-Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object WeakMap]"]=false;var Ln={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){
-try{var n=Nn&&Nn.require&&Nn.require("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\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"}),nt=x({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),tt=x({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),rt=function x(mn){function An(n){if(yu(n)&&!ff(n)&&!(n instanceof Ln)){if(n instanceof On)return n;if(oi.call(n,"__wrapped__"))return Fe(n)}return new On(n)}function kn(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Ln(n){
-this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Fn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new Fn;++t<r;)this.add(n[t]);
-}function Zn(n){this.size=(this.__data__=new Tn(n)).size}function qn(n,t){var r,e=ff(n),u=!e&&of(n),i=!e&&!u&&af(n),o=!e&&!u&&!i&&_f(n),u=(e=e||u||i||o)?A(n.length,ni):[],f=u.length;for(r in n)!t&&!oi.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Se(r,f))||u.push(r);return u}function Qn(n){var t=n.length;return t?n[ir(0,t-1)]:T}function et(n,t){return De(Lr(n),pt(t,0,n.length))}function ut(n){return De(Lr(n))}function it(n,t,r){(r===T||lu(n[t],r))&&(r!==T||t in n)||st(n,t,r);
-}function ot(n,t,r){var e=n[t];oi.call(n,t)&&lu(e,r)&&(r!==T||t in n)||st(n,t,r)}function ft(n,t){for(var r=n.length;r--;)if(lu(n[r][0],t))return r;return-1}function ct(n,t,r,e){return uo(n,function(n,u,i){t(e,n,r(n),i)}),e}function at(n,t){return n&&Cr(t,Wu(t),n)}function lt(n,t){return n&&Cr(t,Uu(t),n)}function st(n,t,r){"__proto__"==t&&Ai?Ai(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function ht(n,t){for(var r=-1,e=t.length,u=Ku(e),i=null==n;++r<e;)u[r]=i?T:Ru(n,t[r]);return u;
-}function pt(n,t,r){return n===n&&(r!==T&&(n=n<=r?n:r),t!==T&&(n=n>=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!du(n))return n;if(u=ff(n)){if(f=me(n),!c)return Lr(n,f)}else{var s=vo(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(af(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Bn[s])return i?n:{};f=ke(n,s,c)}}if(o||(o=new Zn),
-i=o.get(n))return i;if(o.set(n,f),pf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(sf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Uu:Wu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=Wu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Qu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ti("Expected a function");
-return bo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,E(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function bt(n,t){var r=true;return uo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function xt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===T?o===o&&!wu(o):r(o,f)))var f=o,c=i;
-}return c}function jt(n,t){var r=[];return uo(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function wt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=Ee),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?wt(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function mt(n,t){return n&&oo(n,t,Wu)}function At(n,t){return n&&fo(n,t,Wu)}function kt(n,t){return i(t,function(t){return _u(n[t])})}function Et(n,t){t=Sr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[Me(t[r++])];return r&&r==e?n:T}function St(n,t,r){return t=t(n),
-ff(n)?t:a(t,r(n))}function Ot(n){if(null==n)return n===T?"[object Undefined]":"[object Null]";if(mi&&mi in Qu(n)){var t=oi.call(n,mi),r=n[mi];try{n[mi]=T;var e=true}catch(n){}var u=ai.call(n);e&&(t?n[mi]=r:delete n[mi]),n=u}else n=ai.call(n);return n}function It(n,t){return n>t}function Rt(n,t){return null!=n&&oi.call(n,t)}function zt(n,t){return null!=n&&t in Qu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Ku(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,E(t))),s=Ci(p.length,s),
-l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;if(v?!O(v,d):!e(h,d,r)){for(a=i;--a;){var y=l[a];if(y?!O(y,d):!e(n[a],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Ut(n,t,r,e){return mt(n,function(n,u,i){t(e,r(n),u,i)}),e}function Bt(t,r,e){return r=Sr(r,t),t=2>r.length?t:Et(t,hr(r,0,-1)),r=null==t?t:t[Me(Ve(r))],null==r?T:n(r,t,e)}function Lt(n){return yu(n)&&"[object Arguments]"==Ot(n)}function Ct(n){
-return yu(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return yu(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)return true;if(null==n||null==t||!yu(n)&&!yu(t))return n!==n&&t!==t;n:{var i=ff(n),o=ff(t),f=i?"[object Array]":vo(n),c=o?"[object Array]":vo(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)&&af(n)){if(!af(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||_f(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{
+}function A(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function E(n,t){return c(t,function(t){return[t,n[t]]})}function k(n){return function(t){return n(t)}}function S(n,t){return c(t,function(t){return n[t]})}function O(n,t){return n.has(t)}function I(n,t){for(var r=-1,e=n.length;++r<e&&-1<v(t,n[r],0););return r}function R(n,t){for(var r=n.length;r--&&-1<v(t,n[r],0););return r}function z(n){return"\\"+Un[n]}function W(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n];
+}),r}function B(n,t){return function(r){return n(t(r))}}function L(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function U(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function C(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function D(n){if(Rn.test(n)){for(var t=On.lastIndex=0;On.test(n);)++t;n=t}else n=Qn(n);return n}function M(n){return Rn.test(n)?n.match(On)||[]:n.split("");
+}var T,$=1/0,F=NaN,N=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],P=/\b__p\+='';/g,Z=/\b(__p\+=)''\+/g,q=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\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])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,En="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",kn=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+En+mn,"g"),In=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|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="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(" "),Bn={};
+Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false;
+var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true,
+Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){
+try{var n=Nn&&Nn.f&&Nn.f("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\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"}),nt=x({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),tt=x({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),rt=function x(mn){function An(n){if(yu(n)&&!ff(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(oi.call(n,"__wrapped__"))return Fe(n)}return new On(n)}function En(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n,
+this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Fn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new Fn;++t<r;)this.add(n[t]);
+}function Zn(n){this.size=(this.__data__=new Tn(n)).size}function qn(n,t){var r,e=ff(n),u=!e&&of(n),i=!e&&!u&&af(n),o=!e&&!u&&!i&&_f(n),u=(e=e||u||i||o)?A(n.length,ni):[],f=u.length;for(r in n)!t&&!oi.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Se(r,f))||u.push(r);return u}function Qn(n){var t=n.length;return t?n[ir(0,t-1)]:T}function et(n,t){return De(Ur(n),pt(t,0,n.length))}function ut(n){return De(Ur(n))}function it(n,t,r){(r===T||lu(n[t],r))&&(r!==T||t in n)||st(n,t,r);
+}function ot(n,t,r){var e=n[t];oi.call(n,t)&&lu(e,r)&&(r!==T||t in n)||st(n,t,r)}function ft(n,t){for(var r=n.length;r--;)if(lu(n[r][0],t))return r;return-1}function ct(n,t,r,e){return uo(n,function(n,u,i){t(e,n,r(n),i)}),e}function at(n,t){return n&&Cr(t,Wu(t),n)}function lt(n,t){return n&&Cr(t,Bu(t),n)}function st(n,t,r){"__proto__"==t&&Ai?Ai(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function ht(n,t){for(var r=-1,e=t.length,u=Ku(e),i=null==n;++r<e;)u[r]=i?T:Ru(n,t[r]);return u;
+}function pt(n,t,r){return n===n&&(r!==T&&(n=n<=r?n:r),t!==T&&(n=n>=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!du(n))return n;if(u=ff(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=vo(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(af(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=Ee(n,s,c)}}if(o||(o=new Zn),
+i=o.get(n))return i;o.set(n,f),pf(n)?n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}):sf(n)&&n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))});var a=l?a?ve:_e:a?Bu:Wu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=Wu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Qu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ti("Expected a function");
+return bo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,k(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function bt(n,t){var r=true;return uo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function xt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===T?o===o&&!wu(o):r(o,f)))var f=o,c=i;
+}return c}function jt(n,t){var r=[];return uo(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function wt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=ke),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?wt(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function mt(n,t){return n&&oo(n,t,Wu)}function At(n,t){return n&&fo(n,t,Wu)}function Et(n,t){return i(t,function(t){return _u(n[t])})}function kt(n,t){t=Sr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[Me(t[r++])];return r&&r==e?n:T}function St(n,t,r){return t=t(n),
+ff(n)?t:a(t,r(n))}function Ot(n){if(null==n)n=n===T?"[object Undefined]":"[object Null]";else if(mi&&mi in Qu(n)){var t=oi.call(n,mi),r=n[mi];try{n[mi]=T;var e=true}catch(n){}var u=ai.call(n);e&&(t?n[mi]=r:delete n[mi]),n=u}else n=ai.call(n);return n}function It(n,t){return n>t}function Rt(n,t){return null!=n&&oi.call(n,t)}function zt(n,t){return null!=n&&t in Qu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Ku(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,k(t))),s=Ci(p.length,s),
+l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;if(v?!O(v,d):!e(h,d,r)){for(a=i;--a;){var y=l[a];if(y?!O(y,d):!e(n[a],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Bt(n,t,r){var e={};return mt(n,function(n,u,i){t(e,r(n),u,i)}),e}function Lt(t,r,e){return r=Sr(r,t),t=2>r.length?t:kt(t,hr(r,0,-1)),r=null==t?t:t[Me(Ve(r))],null==r?T:n(r,t,e)}function Ut(n){return yu(n)&&"[object Arguments]"==Ot(n)}function Ct(n){
+return yu(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return yu(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!yu(n)&&!yu(t))t=n!==n&&t!==t;else n:{var i=ff(n),o=ff(t),f=i?"[object Array]":vo(n),c=o?"[object Array]":vo(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)&&af(n)){if(!af(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||_f(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{
 if(!(1&r)&&(i=a&&oi.call(n,"__wrapped__"),f=o&&oi.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Zn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Zn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:oi.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;++a<o;){var l=f[a],h=n[l],p=t[l];if(e)var _=i?e(p,h,l,t,n,u):e(h,p,l,n,t,u);if(_===T?h!==p&&!Mt(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l);
 }c&&!s&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),u.delete(n),u.delete(t),t=c}}else t=false;else t=false}}return t}function Tt(n){return yu(n)&&"[object Map]"==vo(n)}function $t(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=Qu(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return false}for(;++u<i;){var f=r[u],c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===T&&!(c in n))return false;
-}else{if(f=new Zn,e)var s=e(a,l,c,n,t,f);if(s===T?!Mt(l,a,3,e,f):!s)return false}}return true}function Ft(n){return!(!du(n)||ci&&ci in n)&&(_u(n)?hi:dn).test(Te(n))}function Nt(n){return yu(n)&&"[object RegExp]"==Ot(n)}function Pt(n){return yu(n)&&"[object Set]"==vo(n)}function Zt(n){return yu(n)&&gu(n.length)&&!!Un[Ot(n)]}function qt(n){return typeof n=="function"?n:null==n?$u:typeof n=="object"?ff(n)?Jt(n[0],n[1]):Ht(n):Zu(n)}function Vt(n){if(!ze(n))return Bi(n);var t,r=[];for(t in Qu(n))oi.call(n,t)&&"constructor"!=t&&r.push(t);
-return r}function Kt(n,t){return n<t}function Gt(n,t){var r=-1,e=su(n)?Ku(n.length):[];return uo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Ht(n){var t=xe(n);return 1==t.length&&t[0][2]?We(t[0][0],t[0][1]):function(r){return r===n||$t(r,n,t)}}function Jt(n,t){return Ie(n)&&t===t&&!du(t)?We(Me(n),t):function(r){var e=Ru(r,n);return e===T&&e===t?zu(r,n):Mt(t,e,3)}}function Yt(n,t,r,e,u){n!==t&&oo(t,function(i,o){if(du(i)){u||(u=new Zn);var f=u,c=Be(n,o),a=Be(t,o),l=f.get(a);if(!l){var l=e?e(c,a,o+"",n,t,f):T,s=l===T;
-if(s){var h=ff(a),p=!h&&af(a),_=!h&&!p&&_f(a),l=a;h||p||_?ff(c)?l=c:hu(c)?l=Lr(c):p?(s=false,l=Ir(a,true)):_?(s=false,l=zr(a,true)):l=[]:xu(a)||of(a)?(l=c,of(c)?l=Ou(c):du(c)&&!_u(c)||(l=Ae(a))):s=false}s&&(f.set(a,l),Yt(l,a,r,e,f),f.delete(a))}it(n,o,l)}else f=e?e(Be(n,o),i,o+"",n,t,u):T,f===T&&(f=i),it(n,o,f)},Uu)}function Qt(n,t){var r=n.length;if(r)return t+=0>t?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[$u],E(ye())),n=Gt(n,function(n,r,u){return{a:c(t,function(t){return t(n)}),
-b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Wr(u[e],i[e]);if(c){if(e>=f){e=c;break n}e=c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return zu(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=Et(n,o);r(f,o)&&lr(i,Sr(o,n),f)}return i}function rr(n){return function(t){return Et(t,n)}}function er(n,t,r,e){var u=e?g:v,i=-1,o=t.length,f=n;for(n===t&&(t=Lr(t)),r&&(f=c(n,E(r)));++i<o;)for(var a=0,l=t[i],l=r?r(l):l;-1<(a=u(f,l,a,e));)f!==n&&xi.call(f,a,1),
-xi.call(n,a,1);return n}function ur(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Se(u)?xi.call(n,u,1):xr(n,u)}}return n}function ir(n,t){return n+Ii(Ti()*(t-n+1))}function or(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=Ii(t/2))&&(n+=n);while(t);return r}function fr(n,t){return xo(Ue(n,t,$u),n+"")}function cr(n){return Qn(Lu(n))}function ar(n,t){var r=Lu(n);return De(r,pt(t,0,r.length))}function lr(n,t,r,e){if(!du(n))return n;t=Sr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){
-var c=Me(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):T;a===T&&(a=du(l)?l:Se(t[u+1])?[]:{})}ot(f,c,a),f=f[c]}return n}function sr(n){return De(Lu(n))}function hr(n,t,r){var e=-1,u=n.length;for(0>t&&(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=Ku(u);++e<u;)r[e]=n[e+t];return r}function pr(n,t){var r;return uo(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function _r(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!wu(o)&&(r?o<=t:o<t)?e=i+1:u=i;
-}return u}return vr(n,t,$u,r)}function vr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=wu(t),a=t===T;u<i;){var l=Ii((u+i)/2),s=r(n[l]),h=s!==T,p=null===s,_=s===s,v=wu(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Ci(i,4294967294)}function gr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r],f=t?t(o):o;if(!r||!lu(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function dr(n){return typeof n=="number"?n:wu(n)?F:+n}function yr(n){
-if(typeof n=="string")return n;if(ff(n))return c(n,yr)+"";if(wu(n))return ro?ro.call(n):"";var t=n+"";return"0"==t&&1/n==-$?"-0":t}function br(n,t,r){var e=-1,u=o,i=n.length,c=true,a=[],l=a;if(r)c=false,u=f;else if(200<=i){if(u=t?null:so(n))return L(u);c=false,u=O,l=new Nn}else l=t?[]:a;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(c&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;t&&l.push(h),a.push(s)}else u(l,h,r)||(l!==a&&l.push(h),a.push(s))}return a}function xr(n,t){return t=Sr(t,n),
-n=2>t.length?n:Et(n,hr(t,0,-1)),null==n||delete n[Me(Ve(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?hr(n,e?0:i,e?i+1:u):hr(n,e?i+1:0,e?u:i)}function wr(n,t){var r=n;return r instanceof Ln&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mr(n,t,r){var e=n.length;if(2>e)return e?br(n[0]):[];for(var u=-1,i=Ku(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=yt(i[u]||o,n[f],t,r));return br(wt(i,1),t,r)}function Ar(n,t,r){
-for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:T);return o}function kr(n){return hu(n)?n:[]}function Er(n){return typeof n=="function"?n:$u}function Sr(n,t){return ff(n)?n:Ie(n,t)?[n]:jo(Iu(n))}function Or(n,t,r){var e=n.length;return r=r===T?e:r,!t&&r>=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=gi?gi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new vi(t).set(new vi(n)),t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length);
-}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=wu(n),o=t!==T,f=null===t,c=t===t,a=wu(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Ur(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Li(i-o,0),l=Ku(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];return l}function Br(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Li(i-f,0),s=Ku(l+a);
-for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Lr(n,t){var r=-1,e=n.length;for(t||(t=Ku(e));++r<e;)t[r]=n[r];return t}function Cr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):T;c===T&&(c=n[f]),u?st(r,f,c):ot(r,f,c)}return r}function Dr(n,t){return Cr(n,po(n),t)}function Mr(n,t){return Cr(n,_o(n),t)}function Tr(n,r){return function(e,u){var i=ff(e)?t:ct,o=r?r():{};return i(e,n,ye(u,2),o);
-}}function $r(n){return fr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:T,o=2<u?r[2]:T,i=3<n.length&&typeof i=="function"?(u--,i):T;for(o&&Oe(r[0],r[1],o)&&(i=3>u?T:i,u=1),t=Qu(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Fr(n,t){return function(r,e){if(null==r)return r;if(!su(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=Qu(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function Nr(n){return function(t,r,e){var u=-1,i=Qu(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break;
-}return t}}function Pr(n,t,r){function e(){return(this&&this!==$n&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Vr(n);return e}function Zr(n){return function(t){t=Iu(t);var r=Rn.test(t)?M(t):T,e=r?r[0]:t.charAt(0);return t=r?Or(r,1).join(""):t.slice(1),e[n]()+t}}function qr(n){return function(t){return l(Mu(Du(t).replace(En,"")),n,"")}}function Vr(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:
-return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=eo(n.prototype),t=n.apply(r,t);return du(t)?t:r}}function Kr(t,r,e){function u(){for(var o=arguments.length,f=Ku(o),c=o,a=de(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:B(f,a),o-=c.length,o<e?ue(t,r,Jr,u.placeholder,T,f,c,T,T,e-o):n(this&&this!==$n&&this instanceof u?i:t,this,f);
-}var i=Vr(t);return u}function Gr(n){return function(t,r,e){var u=Qu(t);if(!su(t)){var i=ye(r,3);t=Wu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:T}}function Hr(n){return pe(function(t){var r=t.length,e=r,u=On.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ti("Expected a function");if(u&&!o&&"wrapper"==ge(i))var o=new On([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=ge(i),f="wrapper"==u?ho(i):T,o=f&&Re(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[ge(f[0])].apply(o,f[3]):1==i.length&&Re(i)?o[u]():o.thru(i);
-return function(){var n=arguments,e=n[0];if(o&&1==n.length&&ff(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Jr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Ku(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=de(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Ur(y,e,u,_)),i&&(y=Br(y,i,o,_)),d-=x,_&&d<a)return j=B(y,j),ue(n,t,Jr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Ci(f.length,x),m=Lr(y);w--;){
-var A=f[w];y[w]=Se(A,x)?m[A]:T}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==$n&&this instanceof l&&(b=g||Vr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?T:Vr(n);return l}function Yr(n,t){return function(r,e){return Ut(r,n,t(e),{})}}function Qr(n,t){return function(r,e){var u;if(r===T&&e===T)return t;if(r!==T&&(u=r),e!==T){if(u===T)return e;typeof r=="string"||typeof e=="string"?(r=yr(r),e=yr(e)):(r=dr(r),e=dr(e)),u=n(r,e)}return u}}function Xr(t){return pe(function(r){
-return r=c(r,E(ye())),fr(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ne(n,t){t=t===T?" ":yr(t);var r=t.length;return 2>r?r?or(t,n):t:(r=or(t,Oi(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Ku(l+c),h=this&&this!==$n&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];return n(h,o?e:this,s)}var o=1&r,f=Vr(t);return i}function re(n){return function(t,r,e){
-e&&typeof e!="number"&&Oe(t,r,e)&&(r=e=T),t=Au(t),r===T?(r=t,t=0):r=Au(r),e=e===T?t<r?1:-1:Au(e);var u=-1;r=Li(Oi((r-t)/(e||1)),0);for(var i=Ku(r);r--;)i[n?r:++u]=t,t+=e;return i}}function ee(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=Su(t),r=Su(r)),n(t,r)}}function ue(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:T;o=l?T:o;var h=l?i:T;return i=l?T:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(T,u),Re(n)&&yo(r,u),r.placeholder=e,Le(r,n,t)}function ie(n){
-var t=Yu[n];return function(n,r){if(n=Su(n),r=null==r?0:Ci(ku(r),292)){var e=(Iu(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(Iu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function oe(n){return function(t){var r=vo(t);return"[object Map]"==r?W(t):"[object Set]"==r?C(t):k(t,n(t))}}function fe(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ti("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=T),o=o===T?o:Li(ku(o),0),f=f===T?f:ku(f),a-=u?u.length:0,64&t){
-var l=e,s=u;e=u=T}var h=c?T:ho(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Ur(e,r,h[4]):r,i[4]=e?B(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Br(e,r,h[6]):r,i[6]=e?B(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ci(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]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),c=t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),Le((h?co:yo)(c,i),n,t)}function ce(n,t,r,e){return n===T||lu(n,ei[r])&&!oi.call(e,r)?t:n}function ae(n,t,r,e,u,i){return du(n)&&du(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return xu(n)?T:n}function se(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;
+}else{if(f=new Zn,e)var s=e(a,l,c,n,t,f);if(s===T?!Mt(l,a,3,e,f):!s)return false}}return true}function Ft(n){return!(!du(n)||ci&&ci in n)&&(_u(n)?hi:dn).test(Te(n))}function Nt(n){return yu(n)&&"[object RegExp]"==Ot(n)}function Pt(n){return yu(n)&&"[object Set]"==vo(n)}function Zt(n){return yu(n)&&gu(n.length)&&!!Bn[Ot(n)]}function qt(n){return typeof n=="function"?n:null==n?$u:typeof n=="object"?ff(n)?Jt(n[0],n[1]):Ht(n):Zu(n)}function Vt(n){if(!ze(n))return Li(n);var t,r=[];for(t in Qu(n))oi.call(n,t)&&"constructor"!=t&&r.push(t);
+return r}function Kt(n,t){return n<t}function Gt(n,t){var r=-1,e=su(n)?Ku(n.length):[];return uo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Ht(n){var t=xe(n);return 1==t.length&&t[0][2]?We(t[0][0],t[0][1]):function(r){return r===n||$t(r,n,t)}}function Jt(n,t){return Ie(n)&&t===t&&!du(t)?We(Me(n),t):function(r){var e=Ru(r,n);return e===T&&e===t?zu(r,n):Mt(t,e,3)}}function Yt(n,t,r,e,u){n!==t&&oo(t,function(i,o){if(u||(u=new Zn),du(i)){var f=u,c=Le(n,o),a=Le(t,o),l=f.get(a);if(l)it(n,o,l);else{
+var l=e?e(c,a,o+"",n,t,f):T,s=l===T;if(s){var h=ff(a),p=!h&&af(a),_=!h&&!p&&_f(a),l=a;h||p||_?ff(c)?l=c:hu(c)?l=Ur(c):p?(s=false,l=Ir(a,true)):_?(s=false,l=zr(a,true)):l=[]:xu(a)||of(a)?(l=c,of(c)?l=Ou(c):du(c)&&!_u(c)||(l=Ae(a))):s=false}s&&(f.set(a,l),Yt(l,a,r,e,f),f.delete(a)),it(n,o,l)}}else f=e?e(Le(n,o),i,o+"",n,t,u):T,f===T&&(f=i),it(n,o,f)},Bu)}function Qt(n,t){var r=n.length;if(r)return t+=0>t?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[$u],k(ye())),n=Gt(n,function(n){return{
+a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Wr(u[e],i[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return zu(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=kt(n,o);r(f,o)&&lr(i,Sr(o,n),f)}return i}function rr(n){return function(t){return kt(t,n)}}function er(n,t,r,e){var u=e?g:v,i=-1,o=t.length,f=n;for(n===t&&(t=Ur(t)),
+r&&(f=c(n,k(r)));++i<o;)for(var a=0,l=t[i],l=r?r(l):l;-1<(a=u(f,l,a,e));)f!==n&&xi.call(f,a,1),xi.call(n,a,1);return n}function ur(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Se(u)?xi.call(n,u,1):xr(n,u)}}}function ir(n,t){return n+Ii(Ti()*(t-n+1))}function or(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=Ii(t/2))&&(n+=n);while(t);return r}function fr(n,t){return xo(Be(n,t,$u),n+"")}function cr(n){return Qn(Uu(n))}function ar(n,t){var r=Uu(n);
+return De(r,pt(t,0,r.length))}function lr(n,t,r,e){if(!du(n))return n;t=Sr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=Me(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):T;a===T&&(a=du(l)?l:Se(t[u+1])?[]:{})}ot(f,c,a),f=f[c]}return n}function sr(n){return De(Uu(n))}function hr(n,t,r){var e=-1,u=n.length;for(0>t&&(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=Ku(u);++e<u;)r[e]=n[e+t];return r}function pr(n,t){var r;return uo(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}
+function _r(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!wu(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return vr(n,t,$u,r)}function vr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=wu(t),a=t===T;u<i;){var l=Ii((u+i)/2),s=r(n[l]),h=s!==T,p=null===s,_=s===s,v=wu(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Ci(i,4294967294)}function gr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){
+var o=n[r],f=t?t(o):o;if(!r||!lu(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function dr(n){return typeof n=="number"?n:wu(n)?F:+n}function yr(n){if(typeof n=="string")return n;if(ff(n))return c(n,yr)+"";if(wu(n))return ro?ro.call(n):"";var t=n+"";return"0"==t&&1/n==-$?"-0":t}function br(n,t,r){var e=-1,u=o,i=n.length,c=true,a=[],l=a;if(r)c=false,u=f;else if(200<=i){if(u=t?null:so(n))return U(u);c=false,u=O,l=new Nn}else l=t?[]:a;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(c&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;
+t&&l.push(h),a.push(s)}else u(l,h,r)||(l!==a&&l.push(h),a.push(s))}return a}function xr(n,t){return t=Sr(t,n),n=2>t.length?n:kt(n,hr(t,0,-1)),null==n||delete n[Me(Ve(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?hr(n,e?0:i,e?i+1:u):hr(n,e?i+1:0,e?u:i)}function wr(n,t){var r=n;return r instanceof Un&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mr(n,t,r){var e=n.length;if(2>e)return e?br(n[0]):[];for(var u=-1,i=Ku(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=yt(i[u]||o,n[f],t,r));
+return br(wt(i,1),t,r)}function Ar(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:T);return o}function Er(n){return hu(n)?n:[]}function kr(n){return typeof n=="function"?n:$u}function Sr(n,t){return ff(n)?n:Ie(n,t)?[n]:jo(Iu(n))}function Or(n,t,r){var e=n.length;return r=r===T?e:r,!t&&r>=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=gi?gi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new vi(t).set(new vi(n)),
+t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=wu(n),o=t!==T,f=null===t,c=t===t,a=wu(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Br(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Ui(i-o,0),l=Ku(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];
+return l}function Lr(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Ui(i-f,0),s=Ku(l+a);for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Ur(n,t){var r=-1,e=n.length;for(t||(t=Ku(e));++r<e;)t[r]=n[r];return t}function Cr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):T;c===T&&(c=n[f]),u?st(r,f,c):ot(r,f,c)}return r}function Dr(n,t){return Cr(n,po(n),t)}function Mr(n,t){return Cr(n,_o(n),t);
+}function Tr(n,r){return function(e,u){var i=ff(e)?t:ct,o=r?r():{};return i(e,n,ye(u,2),o)}}function $r(n){return fr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:T,o=2<u?r[2]:T,i=3<n.length&&typeof i=="function"?(u--,i):T;for(o&&Oe(r[0],r[1],o)&&(i=3>u?T:i,u=1),t=Qu(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Fr(n,t){return function(r,e){if(null==r)return r;if(!su(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=Qu(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function Nr(n){return function(t,r,e){
+var u=-1,i=Qu(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break}return t}}function Pr(n,t,r){function e(){return(this&&this!==$n&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Vr(n);return e}function Zr(n){return function(t){t=Iu(t);var r=Rn.test(t)?M(t):T,e=r?r[0]:t.charAt(0);return t=r?Or(r,1).join(""):t.slice(1),e[n]()+t}}function qr(n){return function(t){return l(Mu(Du(t).replace(kn,"")),n,"")}}function Vr(n){return function(){var t=arguments;switch(t.length){
+case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=eo(n.prototype),t=n.apply(r,t);return du(t)?t:r}}function Kr(t,r,e){function u(){for(var o=arguments.length,f=Ku(o),c=o,a=de(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:L(f,a),
+o-=c.length,o<e?ue(t,r,Jr,u.placeholder,T,f,c,T,T,e-o):n(this&&this!==$n&&this instanceof u?i:t,this,f)}var i=Vr(t);return u}function Gr(n){return function(t,r,e){var u=Qu(t);if(!su(t)){var i=ye(r,3);t=Wu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:T}}function Hr(n){return pe(function(t){var r=t.length,e=r,u=On.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ti("Expected a function");if(u&&!o&&"wrapper"==ge(i))var o=new On([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=ge(i),f="wrapper"==u?ho(i):T,o=f&&Re(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[ge(f[0])].apply(o,f[3]):1==i.length&&Re(i)?o[u]():o.thru(i);
+return function(){var n=arguments,e=n[0];if(o&&1==n.length&&ff(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Jr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Ku(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=de(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Br(y,e,u,_)),i&&(y=Lr(y,i,o,_)),d-=x,_&&d<a)return j=L(y,j),ue(n,t,Jr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Ci(f.length,x),m=Ur(y);w--;){
+var A=f[w];y[w]=Se(A,x)?m[A]:T}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==$n&&this instanceof l&&(b=g||Vr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?T:Vr(n);return l}function Yr(n,t){return function(r,e){return Bt(r,n,t(e))}}function Qr(n,t){return function(r,e){var u;if(r===T&&e===T)return t;if(r!==T&&(u=r),e!==T){if(u===T)return e;typeof r=="string"||typeof e=="string"?(r=yr(r),e=yr(e)):(r=dr(r),e=dr(e)),u=n(r,e)}return u}}function Xr(t){return pe(function(r){
+return r=c(r,k(ye())),fr(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ne(n,t){t=t===T?" ":yr(t);var r=t.length;return 2>r?r?or(t,n):t:(r=or(t,Oi(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Ku(l+c),h=this&&this!==$n&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];return n(h,o?e:this,s)}var o=1&r,f=Vr(t);return i}function re(n){return function(t,r,e){
+e&&typeof e!="number"&&Oe(t,r,e)&&(r=e=T),t=Au(t),r===T?(r=t,t=0):r=Au(r),e=e===T?t<r?1:-1:Au(e);var u=-1;r=Ui(Oi((r-t)/(e||1)),0);for(var i=Ku(r);r--;)i[n?r:++u]=t,t+=e;return i}}function ee(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=Su(t),r=Su(r)),n(t,r)}}function ue(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:T;o=l?T:o;var h=l?i:T;return i=l?T:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(T,u),Re(n)&&yo(r,u),r.placeholder=e,Ue(r,n,t)}function ie(n){
+var t=Yu[n];return function(n,r){if(n=Su(n),(r=null==r?0:Ci(Eu(r),292))&&Wi(n)){var e=(Iu(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(Iu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function oe(n){return function(t){var r=vo(t);return"[object Map]"==r?W(t):"[object Set]"==r?C(t):E(t,n(t))}}function fe(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ti("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=T),o=o===T?o:Ui(Eu(o),0),f=f===T?f:Eu(f),a-=u?u.length:0,
+64&t){var l=e,s=u;e=u=T}var h=c?T:ho(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ci(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]===T?c?0:n.length:Ui(i[9]-a,0),!f&&24&t&&(t&=-25),Ue((h?co:yo)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||lu(n,ei[r])&&!oi.call(e,r)?t:n}function ae(n,t,r,e,u,i){return du(n)&&du(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return xu(n)?T:n}function se(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 Nn:T;for(i.set(n,t),i.set(t,n);++c<f;){var s=n[c],p=t[c];if(e)var _=o?e(p,s,c,t,n,i):e(s,p,c,n,t,i);if(_!==T){if(_)continue;a=false;break}if(l){if(!h(t,function(n,t){if(!O(l,t)&&(s===n||u(s,n,r,e,i)))return l.push(t)})){a=false;break}}else if(s!==p&&!u(s,p,r,e,i)){a=false;break}}return i.delete(n),i.delete(t),a}function he(n,t,r,e,u,i,o){switch(r){case"[object DataView]":if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)break;n=n.buffer,t=t.buffer;case"[object ArrayBuffer]":
-if(n.byteLength!=t.byteLength||!i(new vi(n),new vi(t)))break;return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return lu(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=W;case"[object Set]":if(f||(f=L),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=se(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(to)return to.call(n)==to.call(t)}
-return false}function pe(n){return xo(Ue(n,T,Ze),n+"")}function _e(n){return St(n,Wu,po)}function ve(n){return St(n,Uu,_o)}function ge(n){for(var t=n.name+"",r=Gi[t],e=oi.call(Gi,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function de(n){return(oi.call(An,"placeholder")?An:n).placeholder}function ye(){var n=An.iteratee||Fu,n=n===Fu?qt:n;return arguments.length?n(arguments[0],arguments[1]):n}function be(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
+if(n.byteLength!=t.byteLength||!i(new vi(n),new vi(t)))break;return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return lu(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=W;case"[object Set]":if(f||(f=U),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=se(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(to)return to.call(n)==to.call(t)}
+return false}function pe(n){return xo(Be(n,T,Ze),n+"")}function _e(n){return St(n,Wu,po)}function ve(n){return St(n,Bu,_o)}function ge(n){for(var t=n.name+"",r=Gi[t],e=oi.call(Gi,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function de(n){return(oi.call(An,"placeholder")?An:n).placeholder}function ye(){var n=An.iteratee||Fu,n=n===Fu?qt:n;return arguments.length?n(arguments[0],arguments[1]):n}function be(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
 }function xe(n){for(var t=Wu(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,u===u&&!du(u)]}return t}function je(n,t){var r=null==n?T:n[t];return Ft(r)?r:T}function we(n,t,r){t=Sr(t,n);for(var e=-1,u=t.length,i=false;++e<u;){var o=Me(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&gu(u)&&Se(o,u)&&(ff(n)||of(n)))}function me(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&oi.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ae(n){
-return typeof n.constructor!="function"||ze(n)?{}:eo(di(n))}function ke(n,t,r){var e=n.constructor;switch(t){case"[object ArrayBuffer]":return Rr(n);case"[object Boolean]":case"[object Date]":return new e(+n);case"[object DataView]":return t=r?Rr(n.buffer):n.buffer,new n.constructor(t,n.byteOffset,n.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
-case"[object Uint16Array]":case"[object Uint32Array]":return zr(n,r);case"[object Map]":return new e;case"[object Number]":case"[object String]":return new e(n);case"[object RegExp]":return t=new n.constructor(n.source,_n.exec(n)),t.lastIndex=n.lastIndex,t;case"[object Set]":return new e;case"[object Symbol]":return to?Qu(to.call(n)):{}}}function Ee(n){return ff(n)||of(n)||!!(ji&&n&&n[ji])}function Se(n,t){var r=typeof n;return t=null==t?9007199254740991:t,!!t&&("number"==r||"symbol"!=r&&bn.test(n))&&-1<n&&0==n%1&&n<t;
-}function Oe(n,t,r){if(!du(r))return false;var e=typeof t;return!!("number"==e?su(r)&&Se(t,r.length):"string"==e&&t in r)&&lu(r[t],n)}function Ie(n,t){if(ff(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!wu(n))||(nn.test(n)||!X.test(n)||null!=t&&n in Qu(t))}function Re(n){var t=ge(n),r=An[t];return typeof r=="function"&&t in Ln.prototype&&(n===r||(t=ho(r),!!t&&n===t[0]))}function ze(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||ei)}function We(n,t){
-return function(r){return null!=r&&(r[n]===t&&(t!==T||n in Qu(r)))}}function Ue(t,r,e){return r=Li(r===T?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Li(u.length-r,0),f=Ku(o);++i<o;)f[i]=u[r+i];for(i=-1,o=Ku(r+1);++i<r;)o[i]=u[i];return o[r]=e(f),n(t,this,o)}}function Be(n,t){if("__proto__"!=t)return n[t]}function Le(n,t,r){var e=t+"";t=xo;var u,i=$e;return u=(u=e.match(an))?u[1].split(ln):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],r=r.join(2<i?", ":" "),e=e.replace(cn,"{\n/* [wrapped with "+r+"] */\n")),
-t(n,e)}function Ce(n){var t=0,r=0;return function(){var e=Di(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(T,arguments)}}function De(n,t){var r=-1,e=n.length,u=e-1;for(t=t===T?e:t;++r<t;){var e=ir(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function Me(n){if(typeof n=="string"||wu(n))return n;var t=n+"";return"0"==t&&1/n==-$?"-0":t}function Te(n){if(null!=n){try{return ii.call(n)}catch(n){}return n+""}return""}function $e(n,t){return r(N,function(r){var e="_."+r[0];
-t&r[1]&&!o(n,e)&&n.push(e)}),n.sort()}function Fe(n){if(n instanceof Ln)return n.clone();var t=new On(n.__wrapped__,n.__chain__);return t.__actions__=Lr(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Ne(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:ku(r),0>r&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Pe(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=ku(r),u=0>r?Li(e+u,0):Ci(u,e-1)),_(n,ye(t,3),u,true)}function Ze(n){return(null==n?0:n.length)?wt(n,1):[];
-}function qe(n){return n&&n.length?n[0]:T}function Ve(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ke(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ge(n){return null==n?n:$i.call(n)}function He(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(hu(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function Je(t,r){if(!t||!t.length)return[];var e=He(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Ye(n){return n=An(n),n.__chain__=true,n;
-}function Qe(n,t){return t(n)}function Xe(){return this}function nu(n,t){return(ff(n)?r:uo)(n,ye(t,3))}function tu(n,t){return(ff(n)?e:io)(n,ye(t,3))}function ru(n,t){return(ff(n)?c:Gt)(n,ye(t,3))}function eu(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function uu(n,t){var r;if(typeof t!="function")throw new ti("Expected a function");return n=ku(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function iu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=iu.placeholder,
-n}function ou(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=ou.placeholder,n}function fu(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Go();if(u(n))return o(n);var r,e=bo;r=n-_,n=t-(n-p),r=g?Ci(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Go(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=bo(i,t),v?e(n):s;if(g)return h=bo(i,t),e(p)}return h===T&&(h=bo(i,t)),
-s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ti("Expected a function");return t=Su(t)||0,du(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(Su(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&lo(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Go())},f}function cu(n,t){if(typeof n!="function"||null!=t&&typeof t!="function")throw new ti("Expected a function");var r=function(){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)};return r.cache=new(cu.Cache||Fn),r}function au(n){if(typeof n!="function")throw new ti("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 lu(n,t){return n===t||n!==n&&t!==t}function su(n){return null!=n&&gu(n.length)&&!_u(n)}function hu(n){return yu(n)&&su(n)}function pu(n){if(!yu(n))return false;
-var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!xu(n)}function _u(n){return!!du(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function vu(n){return typeof n=="number"&&n==ku(n)}function gu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n}function du(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function yu(n){return null!=n&&typeof n=="object";
-}function bu(n){return typeof n=="number"||yu(n)&&"[object Number]"==Ot(n)}function xu(n){return!(!yu(n)||"[object Object]"!=Ot(n))&&(n=di(n),null===n||(n=oi.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ii.call(n)==li))}function ju(n){return typeof n=="string"||!ff(n)&&yu(n)&&"[object String]"==Ot(n)}function wu(n){return typeof n=="symbol"||yu(n)&&"[object Symbol]"==Ot(n)}function mu(n){if(!n)return[];if(su(n))return ju(n)?M(n):Lr(n);if(wi&&n[wi]){n=n[wi]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);
-return r}return t=vo(n),("[object Map]"==t?W:"[object Set]"==t?L:Lu)(n)}function Au(n){return n?(n=Su(n),n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function ku(n){n=Au(n);var t=n%1;return n===n?t?n-t:n:0}function Eu(n){return n?pt(ku(n),0,4294967295):0}function Su(n){if(typeof n=="number")return n;if(wu(n))return F;if(du(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=du(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n;
-}function Ou(n){return Cr(n,Uu(n))}function Iu(n){return null==n?"":yr(n)}function Ru(n,t,r){return n=null==n?T:Et(n,t),n===T?r:n}function zu(n,t){return null!=n&&we(n,t,zt)}function Wu(n){return su(n)?qn(n):Vt(n)}function Uu(n){if(su(n))n=qn(n,true);else if(du(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&oi.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Qu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){
-return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,Wu(n))}function Cu(n){return $f(Iu(n).toLowerCase())}function Du(n){return(n=Iu(n))&&n.replace(xn,Xn).replace(Sn,"")}function Mu(n,t,r){return n=Iu(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Tu(n){return function(){return n}}function $u(n){return n}function Fu(n){return qt(typeof n=="function"?n:_t(n,1))}function Nu(n,t,e){var u=Wu(t),i=kt(t,u);null!=e||du(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=kt(t,Wu(t)));
-var o=!(du(e)&&"chain"in e&&!e.chain),f=_u(n);return r(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__=Lr(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Pu(){}function Zu(n){return Ie(n)?b(Me(n)):rr(n)}function qu(){return[]}function Vu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Ku=mn.Array,Gu=mn.Date,Hu=mn.Error,Ju=mn.Function,Yu=mn.Math,Qu=mn.Object,Xu=mn.RegExp,ni=mn.String,ti=mn.TypeError,ri=Ku.prototype,ei=Qu.prototype,ui=mn["__core-js_shared__"],ii=Ju.prototype.toString,oi=ei.hasOwnProperty,fi=0,ci=function(){
-var n=/[^.]+$/.exec(ui&&ui.keys&&ui.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ai=ei.toString,li=ii.call(Qu),si=$n._,hi=Xu("^"+ii.call(oi).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),pi=Pn?mn.Buffer:T,_i=mn.Symbol,vi=mn.Uint8Array,gi=pi?pi.allocUnsafe:T,di=U(Qu.getPrototypeOf,Qu),yi=Qu.create,bi=ei.propertyIsEnumerable,xi=ri.splice,ji=_i?_i.isConcatSpreadable:T,wi=_i?_i.iterator:T,mi=_i?_i.toStringTag:T,Ai=function(){try{var n=je(Qu,"defineProperty");
-return n({},"",{}),n}catch(n){}}(),ki=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,Ei=Gu&&Gu.now!==$n.Date.now&&Gu.now,Si=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Oi=Yu.ceil,Ii=Yu.floor,Ri=Qu.getOwnPropertySymbols,zi=pi?pi.isBuffer:T,Wi=mn.isFinite,Ui=ri.join,Bi=U(Qu.keys,Qu),Li=Yu.max,Ci=Yu.min,Di=Gu.now,Mi=mn.parseInt,Ti=Yu.random,$i=ri.reverse,Fi=je(mn,"DataView"),Ni=je(mn,"Map"),Pi=je(mn,"Promise"),Zi=je(mn,"Set"),qi=je(mn,"WeakMap"),Vi=je(Qu,"create"),Ki=qi&&new qi,Gi={},Hi=Te(Fi),Ji=Te(Ni),Yi=Te(Pi),Qi=Te(Zi),Xi=Te(qi),no=_i?_i.prototype:T,to=no?no.valueOf:T,ro=no?no.toString:T,eo=function(){
-function n(){}return function(t){return du(t)?yi?yi(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=kn.prototype,An.prototype.constructor=An,On.prototype=eo(kn.prototype),On.prototype.constructor=On,Ln.prototype=eo(kn.prototype),Ln.prototype.constructor=Ln,Mn.prototype.clear=function(){this.__data__=Vi?Vi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
+return typeof n.constructor!="function"||ze(n)?{}:eo(di(n))}function Ee(n,t,r){var e=n.constructor;switch(t){case"[object ArrayBuffer]":return Rr(n);case"[object Boolean]":case"[object Date]":return new e(+n);case"[object DataView]":return t=r?Rr(n.buffer):n.buffer,new n.constructor(t,n.byteOffset,n.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
+case"[object Uint16Array]":case"[object Uint32Array]":return zr(n,r);case"[object Map]":return new e;case"[object Number]":case"[object String]":return new e(n);case"[object RegExp]":return t=new n.constructor(n.source,_n.exec(n)),t.lastIndex=n.lastIndex,t;case"[object Set]":return new e;case"[object Symbol]":return to?Qu(to.call(n)):{}}}function ke(n){return ff(n)||of(n)||!!(ji&&n&&n[ji])}function Se(n,t){var r=typeof n;return t=null==t?9007199254740991:t,!!t&&("number"==r||"symbol"!=r&&bn.test(n))&&-1<n&&0==n%1&&n<t;
+}function Oe(n,t,r){if(!du(r))return false;var e=typeof t;return!!("number"==e?su(r)&&Se(t,r.length):"string"==e&&t in r)&&lu(r[t],n)}function Ie(n,t){if(ff(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!wu(n))||(nn.test(n)||!X.test(n)||null!=t&&n in Qu(t))}function Re(n){var t=ge(n),r=An[t];return typeof r=="function"&&t in Un.prototype&&(n===r||(t=ho(r),!!t&&n===t[0]))}function ze(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||ei)}function We(n,t){
+return function(r){return null!=r&&(r[n]===t&&(t!==T||n in Qu(r)))}}function Be(t,r,e){return r=Ui(r===T?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Ui(u.length-r,0),f=Ku(o);++i<o;)f[i]=u[r+i];for(i=-1,o=Ku(r+1);++i<r;)o[i]=u[i];return o[r]=e(f),n(t,this,o)}}function Le(n,t){if(("constructor"!==t||"function"!=typeof n[t])&&"__proto__"!=t)return n[t]}function Ue(n,t,r){var e=t+"";t=xo;var u,i=$e;return u=(u=e.match(an))?u[1].split(ln):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],
+r=r.join(2<i?", ":" "),e=e.replace(cn,"{\n/* [wrapped with "+r+"] */\n")),t(n,e)}function Ce(n){var t=0,r=0;return function(){var e=Di(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(T,arguments)}}function De(n,t){var r=-1,e=n.length,u=e-1;for(t=t===T?e:t;++r<t;){var e=ir(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function Me(n){if(typeof n=="string"||wu(n))return n;var t=n+"";return"0"==t&&1/n==-$?"-0":t}function Te(n){if(null!=n){try{return ii.call(n)}catch(n){}
+return n+""}return""}function $e(n,t){return r(N,function(r){var e="_."+r[0];t&r[1]&&!o(n,e)&&n.push(e)}),n.sort()}function Fe(n){if(n instanceof Un)return n.clone();var t=new On(n.__wrapped__,n.__chain__);return t.__actions__=Ur(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Ne(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Eu(r),0>r&&(r=Ui(e+r,0)),_(n,ye(t,3),r)):-1}function Pe(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Eu(r),u=0>r?Ui(e+u,0):Ci(u,e-1)),
+_(n,ye(t,3),u,true)}function Ze(n){return(null==n?0:n.length)?wt(n,1):[]}function qe(n){return n&&n.length?n[0]:T}function Ve(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ke(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ge(n){return null==n?n:$i.call(n)}function He(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(hu(n))return t=Ui(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function Je(t,r){if(!t||!t.length)return[];var e=He(t);return null==r?e:c(e,function(t){
+return n(r,T,t)})}function Ye(n){return n=An(n),n.__chain__=true,n}function Qe(n,t){return t(n)}function Xe(){return this}function nu(n,t){return(ff(n)?r:uo)(n,ye(t,3))}function tu(n,t){return(ff(n)?e:io)(n,ye(t,3))}function ru(n,t){return(ff(n)?c:Gt)(n,ye(t,3))}function eu(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function uu(n,t){var r;if(typeof t!="function")throw new ti("Expected a function");return n=Eu(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),
+r}}function iu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=ou.placeholder,n}function fu(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Go();if(u(n))return o(n);var r,e=bo;r=n-_,n=t-(n-p),r=g?Ci(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Go(),r=u(n);if(c=arguments,
+a=this,p=n,r){if(h===T)return _=n=p,h=bo(i,t),v?e(n):s;if(g)return lo(h),h=bo(i,t),e(p)}return h===T&&(h=bo(i,t)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ti("Expected a function");return t=Su(t)||0,du(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Ui(Su(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&lo(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Go())},f}function cu(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 ti("Expected a function");return r.cache=new(cu.Cache||Fn),r}function au(n){if(typeof n!="function")throw new ti("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 lu(n,t){return n===t||n!==n&&t!==t;
+}function su(n){return null!=n&&gu(n.length)&&!_u(n)}function hu(n){return yu(n)&&su(n)}function pu(n){if(!yu(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!xu(n)}function _u(n){return!!du(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function vu(n){return typeof n=="number"&&n==Eu(n)}function gu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n;
+}function du(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function yu(n){return null!=n&&typeof n=="object"}function bu(n){return typeof n=="number"||yu(n)&&"[object Number]"==Ot(n)}function xu(n){return!(!yu(n)||"[object Object]"!=Ot(n))&&(n=di(n),null===n||(n=oi.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ii.call(n)==li))}function ju(n){return typeof n=="string"||!ff(n)&&yu(n)&&"[object String]"==Ot(n)}function wu(n){return typeof n=="symbol"||yu(n)&&"[object Symbol]"==Ot(n);
+}function mu(n){if(!n)return[];if(su(n))return ju(n)?M(n):Ur(n);if(wi&&n[wi]){n=n[wi]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=vo(n),("[object Map]"==t?W:"[object Set]"==t?U:Uu)(n)}function Au(n){return n?(n=Su(n),n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Eu(n){n=Au(n);var t=n%1;return n===n?t?n-t:n:0}function ku(n){return n?pt(Eu(n),0,4294967295):0}function Su(n){if(typeof n=="number")return n;if(wu(n))return F;if(du(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,
+n=du(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Ou(n){return Cr(n,Bu(n))}function Iu(n){return null==n?"":yr(n)}function Ru(n,t,r){return n=null==n?T:kt(n,t),n===T?r:n}function zu(n,t){return null!=n&&we(n,t,zt)}function Wu(n){return su(n)?qn(n):Vt(n)}function Bu(n){if(su(n))n=qn(n,true);else if(du(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&oi.call(n,t))&&e.push(t);n=e}else{if(t=[],
+null!=n)for(r in Qu(n))t.push(r);n=t}return n}function Lu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Uu(n){return null==n?[]:S(n,Wu(n))}function Cu(n){return $f(Iu(n).toLowerCase())}function Du(n){return(n=Iu(n))&&n.replace(xn,Xn).replace(Sn,"")}function Mu(n,t,r){return n=Iu(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Tu(n){return function(){return n}}function $u(n){return n;
+}function Fu(n){return qt(typeof n=="function"?n:_t(n,1))}function Nu(n,t,e){var u=Wu(t),i=Et(t,u);null!=e||du(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=Et(t,Wu(t)));var o=!(du(e)&&"chain"in e&&!e.chain),f=_u(n);return r(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__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Pu(){}
+function Zu(n){return Ie(n)?b(Me(n)):rr(n)}function qu(){return[]}function Vu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Ku=mn.Array,Gu=mn.Date,Hu=mn.Error,Ju=mn.Function,Yu=mn.Math,Qu=mn.Object,Xu=mn.RegExp,ni=mn.String,ti=mn.TypeError,ri=Ku.prototype,ei=Qu.prototype,ui=mn["__core-js_shared__"],ii=Ju.prototype.toString,oi=ei.hasOwnProperty,fi=0,ci=function(){var n=/[^.]+$/.exec(ui&&ui.keys&&ui.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ai=ei.toString,li=ii.call(Qu),si=$n._,hi=Xu("^"+ii.call(oi).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),pi=Pn?mn.Buffer:T,_i=mn.Symbol,vi=mn.Uint8Array,gi=pi?pi.g:T,di=B(Qu.getPrototypeOf,Qu),yi=Qu.create,bi=ei.propertyIsEnumerable,xi=ri.splice,ji=_i?_i.isConcatSpreadable:T,wi=_i?_i.iterator:T,mi=_i?_i.toStringTag:T,Ai=function(){
+try{var n=je(Qu,"defineProperty");return n({},"",{}),n}catch(n){}}(),Ei=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,ki=Gu&&Gu.now!==$n.Date.now&&Gu.now,Si=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Oi=Yu.ceil,Ii=Yu.floor,Ri=Qu.getOwnPropertySymbols,zi=pi?pi.isBuffer:T,Wi=mn.isFinite,Bi=ri.join,Li=B(Qu.keys,Qu),Ui=Yu.max,Ci=Yu.min,Di=Gu.now,Mi=mn.parseInt,Ti=Yu.random,$i=ri.reverse,Fi=je(mn,"DataView"),Ni=je(mn,"Map"),Pi=je(mn,"Promise"),Zi=je(mn,"Set"),qi=je(mn,"WeakMap"),Vi=je(Qu,"create"),Ki=qi&&new qi,Gi={},Hi=Te(Fi),Ji=Te(Ni),Yi=Te(Pi),Qi=Te(Zi),Xi=Te(qi),no=_i?_i.prototype:T,to=no?no.valueOf:T,ro=no?no.toString:T,eo=function(){
+function n(){}return function(t){return du(t)?yi?yi(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=En.prototype,An.prototype.constructor=An,On.prototype=eo(En.prototype),On.prototype.constructor=On,Un.prototype=eo(En.prototype),Un.prototype.constructor=Un,Mn.prototype.clear=function(){this.__data__=Vi?Vi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
 this.size-=n?1:0,n},Mn.prototype.get=function(n){var t=this.__data__;return Vi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):oi.call(t,n)?t[n]:T},Mn.prototype.has=function(n){var t=this.__data__;return Vi?t[n]!==T:oi.call(t,n)},Mn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=Vi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():xi.call(t,n,1),
 --this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1<ft(this.__data__,n)},Tn.prototype.set=function(n,t){var r=this.__data__,e=ft(r,n);return 0>e?(++this.size,r.push([n,t])):r[e][1]=t,this},Fn.prototype.clear=function(){this.size=0,this.__data__={hash:new Mn,map:new(Ni||Tn),string:new Mn}},Fn.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},Fn.prototype.get=function(n){return be(this,n).get(n);
 },Fn.prototype.has=function(n){return be(this,n).has(n)},Fn.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Zn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Zn.prototype.get=function(n){
-return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Ni||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var uo=Fr(mt),io=Fr(At,true),oo=Nr(),fo=Nr(true),co=Ki?function(n,t){return Ki.set(n,t),n}:$u,ao=Ai?function(n,t){return Ai(n,"toString",{configurable:true,enumerable:false,value:Tu(t),writable:true})}:$u,lo=ki||function(n){
-return $n.clearTimeout(n)},so=Zi&&1/L(new Zi([,-0]))[1]==$?function(n){return new Zi(n)}:Pu,ho=Ki?function(n){return Ki.get(n)}:Pu,po=Ri?function(n){return null==n?[]:(n=Qu(n),i(Ri(n),function(t){return bi.call(n,t)}))}:qu,_o=Ri?function(n){for(var t=[];n;)a(t,po(n)),n=di(n);return t}:qu,vo=Ot;(Fi&&"[object DataView]"!=vo(new Fi(new ArrayBuffer(1)))||Ni&&"[object Map]"!=vo(new Ni)||Pi&&"[object Promise]"!=vo(Pi.resolve())||Zi&&"[object Set]"!=vo(new Zi)||qi&&"[object WeakMap]"!=vo(new qi))&&(vo=function(n){
+return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Ni||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var uo=Fr(mt),io=Fr(At,true),oo=Nr(),fo=Nr(true),co=Ki?function(n,t){return Ki.set(n,t),n}:$u,ao=Ai?function(n,t){return Ai(n,"toString",{configurable:true,enumerable:false,value:Tu(t),writable:true})}:$u,lo=Ei||function(n){
+return $n.clearTimeout(n)},so=Zi&&1/U(new Zi([,-0]))[1]==$?function(n){return new Zi(n)}:Pu,ho=Ki?function(n){return Ki.get(n)}:Pu,po=Ri?function(n){return null==n?[]:(n=Qu(n),i(Ri(n),function(t){return bi.call(n,t)}))}:qu,_o=Ri?function(n){for(var t=[];n;)a(t,po(n)),n=di(n);return t}:qu,vo=Ot;(Fi&&"[object DataView]"!=vo(new Fi(new ArrayBuffer(1)))||Ni&&"[object Map]"!=vo(new Ni)||Pi&&"[object Promise]"!=vo(Pi.resolve())||Zi&&"[object Set]"!=vo(new Zi)||qi&&"[object WeakMap]"!=vo(new qi))&&(vo=function(n){
 var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Te(n):"")switch(n){case Hi:return"[object DataView]";case Ji:return"[object Map]";case Yi:return"[object Promise]";case Qi:return"[object Set]";case Xi:return"[object WeakMap]"}return t});var go=ui?_u:Vu,yo=Ce(co),bo=Si||function(n,t){return $n.setTimeout(n,t)},xo=Ce(ao),jo=function(n){n=cu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){
-t.push(e?u.replace(hn,"$1"):r||n)}),t}),wo=fr(function(n,t){return hu(n)?yt(n,wt(t,1,hu,true)):[]}),mo=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),ye(r,2)):[]}),Ao=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),T,r):[]}),ko=fr(function(n){var t=c(n,kr);return t.length&&t[0]===n[0]?Wt(t):[]}),Eo=fr(function(n){var t=Ve(n),r=c(n,kr);return t===Ve(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),So=fr(function(n){var t=Ve(n),r=c(n,kr);return(t=typeof t=="function"?t:T)&&r.pop(),
-r.length&&r[0]===n[0]?Wt(r,T,t):[]}),Oo=fr(Ke),Io=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Ro=fr(function(n){return br(wt(n,1,hu,true))}),zo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T),br(wt(n,1,hu,true),ye(t,2))}),Wo=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return br(wt(n,1,hu,true),T,t)}),Uo=fr(function(n,t){return hu(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,hu))}),Lo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T),
-mr(i(n,hu),ye(t,2))}),Co=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return mr(i(n,hu),T,t)}),Do=fr(He),Mo=fr(function(n){var t=n.length,t=1<t?n[t-1]:T,t=typeof t=="function"?(n.pop(),t):T;return Je(n,t)}),To=pe(function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,u=function(t){return ht(t,n)};return!(1<t||this.__actions__.length)&&e instanceof Ln&&Se(r)?(e=e.slice(r,+r+(t?1:0)),e.__actions__.push({func:Qe,args:[u],thisArg:T}),new On(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(T),
-n})):this.thru(u)}),$o=Tr(function(n,t,r){oi.call(n,r)?++n[r]:st(n,r,1)}),Fo=Gr(Ne),No=Gr(Pe),Po=Tr(function(n,t,r){oi.call(n,r)?n[r].push(t):st(n,r,[t])}),Zo=fr(function(t,r,e){var u=-1,i=typeof r=="function",o=su(t)?Ku(t.length):[];return uo(t,function(t){o[++u]=i?n(r,t,e):Bt(t,r,e)}),o}),qo=Tr(function(n,t,r){st(n,r,t)}),Vo=Tr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Ko=fr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&Oe(n,t[0],t[1])?t=[]:2<r&&Oe(t[0],t[1],t[2])&&(t=[t[0]]),
-Xt(n,wt(t,1),[])}),Go=Ei||function(){return $n.Date.now()},Ho=fr(function(n,t,r){var e=1;if(r.length)var u=B(r,de(Ho)),e=32|e;return fe(n,e,t,r,u)}),Jo=fr(function(n,t,r){var e=3;if(r.length)var u=B(r,de(Jo)),e=32|e;return fe(t,e,n,r,u)}),Yo=fr(function(n,t){return dt(n,1,t)}),Qo=fr(function(n,t,r){return dt(n,Su(t)||0,r)});cu.Cache=Fn;var Xo=fr(function(t,r){r=1==r.length&&ff(r[0])?c(r[0],E(ye())):c(wt(r,1),E(ye()));var e=r.length;return fr(function(u){for(var i=-1,o=Ci(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);
-return n(t,this,u)})}),nf=fr(function(n,t){return fe(n,32,T,t,B(t,de(nf)))}),tf=fr(function(n,t){return fe(n,64,T,t,B(t,de(tf)))}),rf=pe(function(n,t){return fe(n,256,T,T,T,t)}),ef=ee(It),uf=ee(function(n,t){return n>=t}),of=Lt(function(){return arguments}())?Lt:function(n){return yu(n)&&oi.call(n,"callee")&&!bi.call(n,"callee")},ff=Ku.isArray,cf=Vn?E(Vn):Ct,af=zi||Vu,lf=Kn?E(Kn):Dt,sf=Gn?E(Gn):Tt,hf=Hn?E(Hn):Nt,pf=Jn?E(Jn):Pt,_f=Yn?E(Yn):Zt,vf=ee(Kt),gf=ee(function(n,t){return n<=t}),df=$r(function(n,t){
-if(ze(t)||su(t))Cr(t,Wu(t),n);else for(var r in t)oi.call(t,r)&&ot(n,r,t[r])}),yf=$r(function(n,t){Cr(t,Uu(t),n)}),bf=$r(function(n,t,r,e){Cr(t,Uu(t),n,e)}),xf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),jf=pe(ht),wf=fr(function(n,t){n=Qu(n);var r=-1,e=t.length,u=2<e?t[2]:T;for(u&&Oe(t[0],t[1],u)&&(e=1);++r<e;)for(var u=t[r],i=Uu(u),o=-1,f=i.length;++o<f;){var c=i[o],a=n[c];(a===T||lu(a,ei[c])&&!oi.call(n,c))&&(n[c]=u[c])}return n}),mf=fr(function(t){return t.push(T,ae),n(Of,T,t)}),Af=Yr(function(n,t,r){
-null!=t&&typeof t.toString!="function"&&(t=ai.call(t)),n[t]=r},Tu($u)),kf=Yr(function(n,t,r){null!=t&&typeof t.toString!="function"&&(t=ai.call(t)),oi.call(n,t)?n[t].push(r):n[t]=[r]},ye),Ef=fr(Bt),Sf=$r(function(n,t,r){Yt(n,t,r)}),Of=$r(function(n,t,r,e){Yt(n,t,r,e)}),If=pe(function(n,t){var r={};if(null==n)return r;var e=false;t=c(t,function(t){return t=Sr(t,n),e||(e=1<t.length),t}),Cr(n,ve(n),r),e&&(r=_t(r,7,le));for(var u=t.length;u--;)xr(r,t[u]);return r}),Rf=pe(function(n,t){return null==n?{}:nr(n,t);
-}),zf=oe(Wu),Wf=oe(Uu),Uf=qr(function(n,t,r){return t=t.toLowerCase(),n+(r?Cu(t):t)}),Bf=qr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Lf=qr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Cf=Zr("toLowerCase"),Df=qr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Mf=qr(function(n,t,r){return n+(r?" ":"")+$f(t)}),Tf=qr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),$f=Zr("toUpperCase"),Ff=fr(function(t,r){try{return n(t,T,r)}catch(n){return pu(n)?n:new Hu(n)}}),Nf=pe(function(n,t){
-return r(t,function(t){t=Me(t),st(n,t,Ho(n[t],n))}),n}),Pf=Hr(),Zf=Hr(true),qf=fr(function(n,t){return function(r){return Bt(r,n,t)}}),Vf=fr(function(n,t){return function(r){return Bt(n,r,t)}}),Kf=Xr(c),Gf=Xr(u),Hf=Xr(h),Jf=re(),Yf=re(true),Qf=Qr(function(n,t){return n+t},0),Xf=ie("ceil"),nc=Qr(function(n,t){return n/t},1),tc=ie("floor"),rc=Qr(function(n,t){return n*t},1),ec=ie("round"),uc=Qr(function(n,t){return n-t},0);return An.after=function(n,t){if(typeof t!="function")throw new ti("Expected a function");
-return n=ku(n),function(){if(1>--n)return t.apply(this,arguments)}},An.ary=eu,An.assign=df,An.assignIn=yf,An.assignInWith=bf,An.assignWith=xf,An.at=jf,An.before=uu,An.bind=Ho,An.bindAll=Nf,An.bindKey=Jo,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return ff(n)?n:[n]},An.chain=Ye,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(ku(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Ku(Oi(r/t));e<r;)i[u++]=hr(n,e,e+=t);return i},An.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){
-var i=n[t];i&&(u[e++]=i)}return u},An.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Ku(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return a(ff(r)?Lr(r):[r],wt(t,1))},An.cond=function(t){var r=null==t?0:t.length,e=ye();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new ti("Expected a function");return[e(n[0]),n[1]]}):[],fr(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})},An.conforms=function(n){return vt(_t(n,1))},An.constant=Tu,
-An.countBy=$o,An.create=function(n,t){var r=eo(n);return null==t?r:at(r,t)},An.curry=iu,An.curryRight=ou,An.debounce=fu,An.defaults=wf,An.defaultsDeep=mf,An.defer=Yo,An.delay=Qo,An.difference=wo,An.differenceBy=mo,An.differenceWith=Ao,An.drop=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:ku(t),hr(n,0>t?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:ku(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[];
-},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=ku(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:ku(e),0>e&&(e+=u),e=r>e?0:Eu(e);r<e;)n[r++]=t;return n},An.filter=function(n,t){return(ff(n)?i:jt)(n,ye(t,3))},An.flatMap=function(n,t){return wt(ru(n,t),1)},An.flatMapDeep=function(n,t){return wt(ru(n,t),$)},An.flatMapDepth=function(n,t,r){return r=r===T?1:ku(r),
-wt(ru(n,t),r)},An.flatten=Ze,An.flattenDeep=function(n){return(null==n?0:n.length)?wt(n,$):[]},An.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===T?1:ku(t),wt(n,t)):[]},An.flip=function(n){return fe(n,512)},An.flow=Pf,An.flowRight=Zf,An.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},An.functions=function(n){return null==n?[]:kt(n,Wu(n))},An.functionsIn=function(n){return null==n?[]:kt(n,Uu(n))},An.groupBy=Po,An.initial=function(n){
-return(null==n?0:n.length)?hr(n,0,-1):[]},An.intersection=ko,An.intersectionBy=Eo,An.intersectionWith=So,An.invert=Af,An.invertBy=kf,An.invokeMap=Zo,An.iteratee=Fu,An.keyBy=qo,An.keys=Wu,An.keysIn=Uu,An.map=ru,An.mapKeys=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,t(n,e,u),n)}),r},An.mapValues=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,e,t(n,e,u))}),r},An.matches=function(n){return Ht(_t(n,1))},An.matchesProperty=function(n,t){return Jt(n,_t(t,1))},An.memoize=cu,
-An.merge=Sf,An.mergeWith=Of,An.method=qf,An.methodOf=Vf,An.mixin=Nu,An.negate=au,An.nthArg=function(n){return n=ku(n),fr(function(t){return Qt(t,n)})},An.omit=If,An.omitBy=function(n,t){return Bu(n,au(ye(t)))},An.once=function(n){return uu(2,n)},An.orderBy=function(n,t,r,e){return null==n?[]:(ff(t)||(t=null==t?[]:[t]),r=e?T:r,ff(r)||(r=null==r?[]:[r]),Xt(n,t,r))},An.over=Kf,An.overArgs=Xo,An.overEvery=Gf,An.overSome=Hf,An.partial=nf,An.partialRight=tf,An.partition=Vo,An.pick=Rf,An.pickBy=Bu,An.property=Zu,
-An.propertyOf=function(n){return function(t){return null==n?T:Et(n,t)}},An.pull=Oo,An.pullAll=Ke,An.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,ye(r,2)):n},An.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,T,r):n},An.pullAt=Io,An.range=Jf,An.rangeRight=Yf,An.rearg=rf,An.reject=function(n,t){return(ff(n)?i:jt)(n,au(ye(t,3)))},An.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ye(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),
-u.push(e))}return ur(n,u),r},An.rest=function(n,t){if(typeof n!="function")throw new ti("Expected a function");return t=t===T?t:ku(t),fr(n,t)},An.reverse=Ge,An.sampleSize=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:ku(t),(ff(n)?et:ar)(n,t)},An.set=function(n,t,r){return null==n?n:lr(n,t,r)},An.setWith=function(n,t,r,e){return e=typeof e=="function"?e:T,null==n?n:lr(n,t,r,e)},An.shuffle=function(n){return(ff(n)?ut:sr)(n)},An.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&Oe(n,t,r)?(t=0,
-r=e):(t=null==t?0:ku(t),r=r===T?e:ku(r)),hr(n,t,r)):[]},An.sortBy=Ko,An.sortedUniq=function(n){return n&&n.length?gr(n):[]},An.sortedUniqBy=function(n,t){return n&&n.length?gr(n,ye(t,2)):[]},An.split=function(n,t,r){return r&&typeof r!="number"&&Oe(n,t,r)&&(t=r=T),r=r===T?4294967295:r>>>0,r?(n=Iu(n))&&(typeof t=="string"||null!=t&&!hf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ti("Expected a function");return r=null==r?0:Li(ku(r),0),
-fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:ku(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:ku(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n),
-n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ti("Expected a function");return du(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),fu(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Qe,An.toArray=mu,An.toPairs=zf,An.toPairsIn=Wf,An.toPath=function(n){return ff(n)?c(n,Me):wu(n)?[n]:Lr(jo(Iu(n)))},An.toPlainObject=Ou,An.transform=function(n,t,e){var u=ff(n),i=u||af(n)||_f(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:du(n)&&_u(o)?eo(di(n)):{};
-}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return eu(n,1)},An.union=Ro,An.unionBy=zo,An.unionWith=Wo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=He,An.unzipWith=Je,An.update=function(n,t,r){return null!=n&&(r=Er(r),n=lr(n,t,r(Et(n,t)),void 0)),n},An.updateWith=function(n,t,r,e){
-return e=typeof e=="function"?e:T,null!=n&&(r=Er(r),n=lr(n,t,r(Et(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Uu(n))},An.without=Uo,An.words=Mu,An.wrap=function(n,t){return nf(Er(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Co,An.zip=Do,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Mo,An.entries=zf,An.entriesIn=Wf,An.extend=yf,An.extendWith=bf,Nu(An,An),An.add=Qf,An.attempt=Ff,An.camelCase=Uf,An.capitalize=Cu,
+t.push(e?u.replace(hn,"$1"):r||n)}),t}),wo=fr(function(n,t){return hu(n)?yt(n,wt(t,1,hu,true)):[]}),mo=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),ye(r,2)):[]}),Ao=fr(function(n,t){var r=Ve(t);return hu(r)&&(r=T),hu(n)?yt(n,wt(t,1,hu,true),T,r):[]}),Eo=fr(function(n){var t=c(n,Er);return t.length&&t[0]===n[0]?Wt(t):[]}),ko=fr(function(n){var t=Ve(n),r=c(n,Er);return t===Ve(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),So=fr(function(n){var t=Ve(n),r=c(n,Er);return(t=typeof t=="function"?t:T)&&r.pop(),
+r.length&&r[0]===n[0]?Wt(r,T,t):[]}),Oo=fr(Ke),Io=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Ro=fr(function(n){return br(wt(n,1,hu,true))}),zo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T),br(wt(n,1,hu,true),ye(t,2))}),Wo=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return br(wt(n,1,hu,true),T,t)}),Bo=fr(function(n,t){return hu(n)?yt(n,t):[]}),Lo=fr(function(n){return mr(i(n,hu))}),Uo=fr(function(n){var t=Ve(n);return hu(t)&&(t=T),
+mr(i(n,hu),ye(t,2))}),Co=fr(function(n){var t=Ve(n),t=typeof t=="function"?t:T;return mr(i(n,hu),T,t)}),Do=fr(He),Mo=fr(function(n){var t=n.length,t=1<t?n[t-1]:T,t=typeof t=="function"?(n.pop(),t):T;return Je(n,t)}),To=pe(function(n){function t(t){return ht(t,n)}var r=n.length,e=r?n[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Un&&Se(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:Qe,args:[t],thisArg:T}),new On(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(T),
+n})):this.thru(t)}),$o=Tr(function(n,t,r){oi.call(n,r)?++n[r]:st(n,r,1)}),Fo=Gr(Ne),No=Gr(Pe),Po=Tr(function(n,t,r){oi.call(n,r)?n[r].push(t):st(n,r,[t])}),Zo=fr(function(t,r,e){var u=-1,i=typeof r=="function",o=su(t)?Ku(t.length):[];return uo(t,function(t){o[++u]=i?n(r,t,e):Lt(t,r,e)}),o}),qo=Tr(function(n,t,r){st(n,r,t)}),Vo=Tr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Ko=fr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&Oe(n,t[0],t[1])?t=[]:2<r&&Oe(t[0],t[1],t[2])&&(t=[t[0]]),
+Xt(n,wt(t,1),[])}),Go=ki||function(){return $n.Date.now()},Ho=fr(function(n,t,r){var e=1;if(r.length)var u=L(r,de(Ho)),e=32|e;return fe(n,e,t,r,u)}),Jo=fr(function(n,t,r){var e=3;if(r.length)var u=L(r,de(Jo)),e=32|e;return fe(t,e,n,r,u)}),Yo=fr(function(n,t){return dt(n,1,t)}),Qo=fr(function(n,t,r){return dt(n,Su(t)||0,r)});cu.Cache=Fn;var Xo=fr(function(t,r){r=1==r.length&&ff(r[0])?c(r[0],k(ye())):c(wt(r,1),k(ye()));var e=r.length;return fr(function(u){for(var i=-1,o=Ci(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);
+return n(t,this,u)})}),nf=fr(function(n,t){return fe(n,32,T,t,L(t,de(nf)))}),tf=fr(function(n,t){return fe(n,64,T,t,L(t,de(tf)))}),rf=pe(function(n,t){return fe(n,256,T,T,T,t)}),ef=ee(It),uf=ee(function(n,t){return n>=t}),of=Ut(function(){return arguments}())?Ut:function(n){return yu(n)&&oi.call(n,"callee")&&!bi.call(n,"callee")},ff=Ku.isArray,cf=Vn?k(Vn):Ct,af=zi||Vu,lf=Kn?k(Kn):Dt,sf=Gn?k(Gn):Tt,hf=Hn?k(Hn):Nt,pf=Jn?k(Jn):Pt,_f=Yn?k(Yn):Zt,vf=ee(Kt),gf=ee(function(n,t){return n<=t}),df=$r(function(n,t){
+if(ze(t)||su(t))Cr(t,Wu(t),n);else for(var r in t)oi.call(t,r)&&ot(n,r,t[r])}),yf=$r(function(n,t){Cr(t,Bu(t),n)}),bf=$r(function(n,t,r,e){Cr(t,Bu(t),n,e)}),xf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),jf=pe(ht),wf=fr(function(n,t){n=Qu(n);var r=-1,e=t.length,u=2<e?t[2]:T;for(u&&Oe(t[0],t[1],u)&&(e=1);++r<e;)for(var u=t[r],i=Bu(u),o=-1,f=i.length;++o<f;){var c=i[o],a=n[c];(a===T||lu(a,ei[c])&&!oi.call(n,c))&&(n[c]=u[c])}return n}),mf=fr(function(t){return t.push(T,ae),n(Of,T,t)}),Af=Yr(function(n,t,r){
+null!=t&&typeof t.toString!="function"&&(t=ai.call(t)),n[t]=r},Tu($u)),Ef=Yr(function(n,t,r){null!=t&&typeof t.toString!="function"&&(t=ai.call(t)),oi.call(n,t)?n[t].push(r):n[t]=[r]},ye),kf=fr(Lt),Sf=$r(function(n,t,r){Yt(n,t,r)}),Of=$r(function(n,t,r,e){Yt(n,t,r,e)}),If=pe(function(n,t){var r={};if(null==n)return r;var e=false;t=c(t,function(t){return t=Sr(t,n),e||(e=1<t.length),t}),Cr(n,ve(n),r),e&&(r=_t(r,7,le));for(var u=t.length;u--;)xr(r,t[u]);return r}),Rf=pe(function(n,t){return null==n?{}:nr(n,t);
+}),zf=oe(Wu),Wf=oe(Bu),Bf=qr(function(n,t,r){return t=t.toLowerCase(),n+(r?Cu(t):t)}),Lf=qr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Uf=qr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Cf=Zr("toLowerCase"),Df=qr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Mf=qr(function(n,t,r){return n+(r?" ":"")+$f(t)}),Tf=qr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),$f=Zr("toUpperCase"),Ff=fr(function(t,r){try{return n(t,T,r)}catch(n){return pu(n)?n:new Hu(n)}}),Nf=pe(function(n,t){
+return r(t,function(t){t=Me(t),st(n,t,Ho(n[t],n))}),n}),Pf=Hr(),Zf=Hr(true),qf=fr(function(n,t){return function(r){return Lt(r,n,t)}}),Vf=fr(function(n,t){return function(r){return Lt(n,r,t)}}),Kf=Xr(c),Gf=Xr(u),Hf=Xr(h),Jf=re(),Yf=re(true),Qf=Qr(function(n,t){return n+t},0),Xf=ie("ceil"),nc=Qr(function(n,t){return n/t},1),tc=ie("floor"),rc=Qr(function(n,t){return n*t},1),ec=ie("round"),uc=Qr(function(n,t){return n-t},0);return An.after=function(n,t){if(typeof t!="function")throw new ti("Expected a function");
+return n=Eu(n),function(){if(1>--n)return t.apply(this,arguments)}},An.ary=eu,An.assign=df,An.assignIn=yf,An.assignInWith=bf,An.assignWith=xf,An.at=jf,An.before=uu,An.bind=Ho,An.bindAll=Nf,An.bindKey=Jo,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return ff(n)?n:[n]},An.chain=Ye,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Ui(Eu(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Ku(Oi(r/t));e<r;)i[u++]=hr(n,e,e+=t);return i},An.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){
+var i=n[t];i&&(u[e++]=i)}return u},An.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Ku(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return a(ff(r)?Ur(r):[r],wt(t,1))},An.cond=function(t){var r=null==t?0:t.length,e=ye();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new ti("Expected a function");return[e(n[0]),n[1]]}):[],fr(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})},An.conforms=function(n){return vt(_t(n,1))},An.constant=Tu,
+An.countBy=$o,An.create=function(n,t){var r=eo(n);return null==t?r:at(r,t)},An.curry=iu,An.curryRight=ou,An.debounce=fu,An.defaults=wf,An.defaultsDeep=mf,An.defer=Yo,An.delay=Qo,An.difference=wo,An.differenceBy=mo,An.differenceWith=Ao,An.drop=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Eu(t),hr(n,0>t?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Eu(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[];
+},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Eu(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Eu(e),0>e&&(e+=u),e=r>e?0:ku(e);r<e;)n[r++]=t;return n},An.filter=function(n,t){return(ff(n)?i:jt)(n,ye(t,3))},An.flatMap=function(n,t){return wt(ru(n,t),1)},An.flatMapDeep=function(n,t){return wt(ru(n,t),$)},An.flatMapDepth=function(n,t,r){return r=r===T?1:Eu(r),
+wt(ru(n,t),r)},An.flatten=Ze,An.flattenDeep=function(n){return(null==n?0:n.length)?wt(n,$):[]},An.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===T?1:Eu(t),wt(n,t)):[]},An.flip=function(n){return fe(n,512)},An.flow=Pf,An.flowRight=Zf,An.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},An.functions=function(n){return null==n?[]:Et(n,Wu(n))},An.functionsIn=function(n){return null==n?[]:Et(n,Bu(n))},An.groupBy=Po,An.initial=function(n){
+return(null==n?0:n.length)?hr(n,0,-1):[]},An.intersection=Eo,An.intersectionBy=ko,An.intersectionWith=So,An.invert=Af,An.invertBy=Ef,An.invokeMap=Zo,An.iteratee=Fu,An.keyBy=qo,An.keys=Wu,An.keysIn=Bu,An.map=ru,An.mapKeys=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,t(n,e,u),n)}),r},An.mapValues=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,e,t(n,e,u))}),r},An.matches=function(n){return Ht(_t(n,1))},An.matchesProperty=function(n,t){return Jt(n,_t(t,1))},An.memoize=cu,
+An.merge=Sf,An.mergeWith=Of,An.method=qf,An.methodOf=Vf,An.mixin=Nu,An.negate=au,An.nthArg=function(n){return n=Eu(n),fr(function(t){return Qt(t,n)})},An.omit=If,An.omitBy=function(n,t){return Lu(n,au(ye(t)))},An.once=function(n){return uu(2,n)},An.orderBy=function(n,t,r,e){return null==n?[]:(ff(t)||(t=null==t?[]:[t]),r=e?T:r,ff(r)||(r=null==r?[]:[r]),Xt(n,t,r))},An.over=Kf,An.overArgs=Xo,An.overEvery=Gf,An.overSome=Hf,An.partial=nf,An.partialRight=tf,An.partition=Vo,An.pick=Rf,An.pickBy=Lu,An.property=Zu,
+An.propertyOf=function(n){return function(t){return null==n?T:kt(n,t)}},An.pull=Oo,An.pullAll=Ke,An.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,ye(r,2)):n},An.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,T,r):n},An.pullAt=Io,An.range=Jf,An.rangeRight=Yf,An.rearg=rf,An.reject=function(n,t){return(ff(n)?i:jt)(n,au(ye(t,3)))},An.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ye(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),
+u.push(e))}return ur(n,u),r},An.rest=function(n,t){if(typeof n!="function")throw new ti("Expected a function");return t=t===T?t:Eu(t),fr(n,t)},An.reverse=Ge,An.sampleSize=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Eu(t),(ff(n)?et:ar)(n,t)},An.set=function(n,t,r){return null==n?n:lr(n,t,r)},An.setWith=function(n,t,r,e){return e=typeof e=="function"?e:T,null==n?n:lr(n,t,r,e)},An.shuffle=function(n){return(ff(n)?ut:sr)(n)},An.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&Oe(n,t,r)?(t=0,
+r=e):(t=null==t?0:Eu(t),r=r===T?e:Eu(r)),hr(n,t,r)):[]},An.sortBy=Ko,An.sortedUniq=function(n){return n&&n.length?gr(n):[]},An.sortedUniqBy=function(n,t){return n&&n.length?gr(n,ye(t,2)):[]},An.split=function(n,t,r){return r&&typeof r!="number"&&Oe(n,t,r)&&(t=r=T),r=r===T?4294967295:r>>>0,r?(n=Iu(n))&&(typeof t=="string"||null!=t&&!hf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ti("Expected a function");return r=null==r?0:Ui(Eu(r),0),
+fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Eu(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Eu(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n),
+n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ti("Expected a function");return du(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),fu(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Qe,An.toArray=mu,An.toPairs=zf,An.toPairsIn=Wf,An.toPath=function(n){return ff(n)?c(n,Me):wu(n)?[n]:Ur(jo(Iu(n)))},An.toPlainObject=Ou,An.transform=function(n,t,e){var u=ff(n),i=u||af(n)||_f(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:du(n)&&_u(o)?eo(di(n)):{};
+}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return eu(n,1)},An.union=Ro,An.unionBy=zo,An.unionWith=Wo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=He,An.unzipWith=Je,An.update=function(n,t,r){return null==n?n:lr(n,t,kr(r)(kt(n,t)),void 0)},An.updateWith=function(n,t,r,e){
+return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,kr(r)(kt(n,t)),e)),n},An.values=Uu,An.valuesIn=function(n){return null==n?[]:S(n,Bu(n))},An.without=Bo,An.words=Mu,An.wrap=function(n,t){return nf(kr(t),n)},An.xor=Lo,An.xorBy=Uo,An.xorWith=Co,An.zip=Do,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Mo,An.entries=zf,An.entriesIn=Wf,An.extend=yf,An.extendWith=bf,Nu(An,An),An.add=Qf,An.attempt=Ff,An.camelCase=Bf,An.capitalize=Cu,
 An.ceil=Xf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=Su(r),r=r===r?r:0),t!==T&&(t=Su(t),t=t===t?t:0),pt(Su(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,Wu(t))},An.deburr=Du,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=nc,An.endsWith=function(n,t,r){
-n=Iu(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(ku(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=lu,An.escape=function(n){return(n=Iu(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Iu(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=ff(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=Fo,An.findIndex=Ne,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=No,An.findLastIndex=Pe,An.findLastKey=function(n,t){return p(n,ye(t,3),At);
-},An.floor=tc,An.forEach=nu,An.forEachRight=tu,An.forIn=function(n,t){return null==n?n:oo(n,ye(t,3),Uu)},An.forInRight=function(n,t){return null==n?n:fo(n,ye(t,3),Uu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Ru,An.gt=ef,An.gte=uf,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=zu,An.head=qe,An.identity=$u,An.includes=function(n,t,r,e){return n=su(n)?n:Lu(n),r=r&&!e?ku(r):0,e=n.length,0>r&&(r=Li(e+r,0)),ju(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<v(n,t,r);
-},An.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:ku(r),0>r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=Au(t),r===T?(r=t,t=0):r=Au(r),n=Su(n),n>=Ci(t,r)&&n<Li(t,r)},An.invoke=Ef,An.isArguments=of,An.isArray=ff,An.isArrayBuffer=cf,An.isArrayLike=su,An.isArrayLikeObject=hu,An.isBoolean=function(n){return true===n||false===n||yu(n)&&"[object Boolean]"==Ot(n)},An.isBuffer=af,An.isDate=lf,An.isElement=function(n){return yu(n)&&1===n.nodeType&&!xu(n)},An.isEmpty=function(n){
+n=Iu(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Eu(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=lu,An.escape=function(n){return(n=Iu(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Iu(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=ff(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=Fo,An.findIndex=Ne,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=No,An.findLastIndex=Pe,An.findLastKey=function(n,t){return p(n,ye(t,3),At);
+},An.floor=tc,An.forEach=nu,An.forEachRight=tu,An.forIn=function(n,t){return null==n?n:oo(n,ye(t,3),Bu)},An.forInRight=function(n,t){return null==n?n:fo(n,ye(t,3),Bu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Ru,An.gt=ef,An.gte=uf,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=zu,An.head=qe,An.identity=$u,An.includes=function(n,t,r,e){return n=su(n)?n:Uu(n),r=r&&!e?Eu(r):0,e=n.length,0>r&&(r=Ui(e+r,0)),ju(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<v(n,t,r);
+},An.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Eu(r),0>r&&(r=Ui(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=Au(t),r===T?(r=t,t=0):r=Au(r),n=Su(n),n>=Ci(t,r)&&n<Ui(t,r)},An.invoke=kf,An.isArguments=of,An.isArray=ff,An.isArrayBuffer=cf,An.isArrayLike=su,An.isArrayLikeObject=hu,An.isBoolean=function(n){return true===n||false===n||yu(n)&&"[object Boolean]"==Ot(n)},An.isBuffer=af,An.isDate=lf,An.isElement=function(n){return yu(n)&&1===n.nodeType&&!xu(n)},An.isEmpty=function(n){
 if(null==n)return true;if(su(n)&&(ff(n)||typeof n=="string"||typeof n.splice=="function"||af(n)||_f(n)||of(n)))return!n.length;var t=vo(n);if("[object Map]"==t||"[object Set]"==t)return!n.size;if(ze(n))return!Vt(n).length;for(var r in n)if(oi.call(n,r))return false;return true},An.isEqual=function(n,t){return Mt(n,t)},An.isEqualWith=function(n,t,r){var e=(r=typeof r=="function"?r:T)?r(n,t):T;return e===T?Mt(n,t,T,r):!!e},An.isError=pu,An.isFinite=function(n){return typeof n=="number"&&Wi(n)},An.isFunction=_u,
 An.isInteger=vu,An.isLength=gu,An.isMap=sf,An.isMatch=function(n,t){return n===t||$t(n,t,xe(t))},An.isMatchWith=function(n,t,r){return r=typeof r=="function"?r:T,$t(n,t,xe(t),r)},An.isNaN=function(n){return bu(n)&&n!=+n},An.isNative=function(n){if(go(n))throw new Hu("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return Ft(n)},An.isNil=function(n){return null==n},An.isNull=function(n){return null===n},An.isNumber=bu,An.isObject=du,An.isObjectLike=yu,An.isPlainObject=xu,An.isRegExp=hf,
-An.isSafeInteger=function(n){return vu(n)&&-9007199254740991<=n&&9007199254740991>=n},An.isSet=pf,An.isString=ju,An.isSymbol=wu,An.isTypedArray=_f,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return yu(n)&&"[object WeakMap]"==vo(n)},An.isWeakSet=function(n){return yu(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Ui.call(n,t)},An.kebabCase=Bf,An.last=Ve,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=ku(r),u=0>u?Li(e+u,0):Ci(u,e-1)),
-t===t)n:{for(r=u+1;r--;)if(n[r]===t){n=r;break n}n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Cf,An.lt=vf,An.lte=gf,An.max=function(n){return n&&n.length?xt(n,$u,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,$u)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,$u,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=qu,An.stubFalse=Vu,An.stubObject=function(){
-return{}},An.stubString=function(){return""},An.stubTrue=function(){return true},An.multiply=rc,An.nth=function(n,t){return n&&n.length?Qt(n,ku(t)):T},An.noConflict=function(){return $n._===this&&($n._=si),this},An.noop=Pu,An.now=Go,An.pad=function(n,t,r){n=Iu(n);var e=(t=ku(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Ii(t),r)+n+ne(Oi(t),r))},An.padEnd=function(n,t,r){n=Iu(n);var e=(t=ku(t))?D(n):0;return t&&e<t?n+ne(t-e,r):n},An.padStart=function(n,t,r){n=Iu(n);var e=(t=ku(t))?D(n):0;return t&&e<t?ne(t-e,r)+n:n;
-},An.parseInt=function(n,t,r){return r||null==t?t=0:t&&(t=+t),Mi(Iu(n).replace(on,""),t||0)},An.random=function(n,t,r){if(r&&typeof r!="boolean"&&Oe(n,t,r)&&(t=r=T),r===T&&(typeof t=="boolean"?(r=t,t=T):typeof n=="boolean"&&(r=n,n=T)),n===T&&t===T?(n=0,t=1):(n=Au(n),t===T?(t=n,n=0):t=Au(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Ti(),Ci(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=ff(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,uo)},An.reduceRight=function(n,t,r){
-var e=ff(n)?s:j,u=3>arguments.length;return e(n,ye(t,4),r,u,io)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:ku(t),or(Iu(n),t)},An.replace=function(){var n=arguments,t=Iu(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++e<u;){var i=null==n?T:n[Me(t[e])];i===T&&(e=u,i=r),n=_u(i)?i.call(n):i}return n},An.round=ec,An.runInContext=x,An.sample=function(n){return(ff(n)?Qn:cr)(n)},An.size=function(n){if(null==n)return 0;
-if(su(n))return ju(n)?D(n):n.length;var t=vo(n);return"[object Map]"==t||"[object Set]"==t?n.size:Vt(n).length},An.snakeCase=Df,An.some=function(n,t,r){var e=ff(n)?h:pr;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.sortedIndex=function(n,t){return _r(n,t)},An.sortedIndexBy=function(n,t,r){return vr(n,t,ye(r,2))},An.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=_r(n,t);if(e<r&&lu(n[e],t))return e}return-1},An.sortedLastIndex=function(n,t){return _r(n,t,true)},An.sortedLastIndexBy=function(n,t,r){
-return vr(n,t,ye(r,2),true)},An.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=_r(n,t,true)-1;if(lu(n[r],t))return r}return-1},An.startCase=Mf,An.startsWith=function(n,t,r){return n=Iu(n),r=null==r?0:pt(ku(r),0,n.length),t=yr(t),n.slice(r,r+t.length)==t},An.subtract=uc,An.sum=function(n){return n&&n.length?m(n,$u):0},An.sumBy=function(n,t){return n&&n.length?m(n,ye(t,2)):0},An.template=function(n,t,r){var e=An.templateSettings;r&&Oe(n,t,r)&&(t=T),n=Iu(n),t=bf({},t,e,ce),r=bf({},t.imports,e.imports,ce);
-var u,i,o=Wu(r),f=S(r,o),c=0;r=t.interpolate||jn;var a="__p+='";r=Xu((t.escape||jn).source+"|"+r.source+"|"+(r===Q?pn:jn).source+"|"+(t.evaluate||jn).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(wn,z),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(i?a.replace(P,""):a).replace(Z,"$1").replace(q,"$1;"),
-a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=Ff(function(){return Ju(o,l+"return "+a).apply(T,f)}),t.source=a,pu(t))throw t;return t},An.times=function(n,t){if(n=ku(n),1>n||9007199254740991<n)return[];var r=4294967295,e=Ci(n,4294967295);for(t=ye(t),n-=4294967295,e=A(e,t);++r<n;)t(r);return e},An.toFinite=Au,An.toInteger=ku,An.toLength=Eu,An.toLower=function(n){
-return Iu(n).toLowerCase()},An.toNumber=Su,An.toSafeInteger=function(n){return n?pt(ku(n),-9007199254740991,9007199254740991):0===n?n:0},An.toString=Iu,An.toUpper=function(n){return Iu(n).toUpperCase()},An.trim=function(n,t,r){return(n=Iu(n))&&(r||t===T)?n.replace(un,""):n&&(t=yr(t))?(n=M(n),r=M(t),t=I(n,r),r=R(n,r)+1,Or(n,t,r).join("")):n},An.trimEnd=function(n,t,r){return(n=Iu(n))&&(r||t===T)?n.replace(fn,""):n&&(t=yr(t))?(n=M(n),t=R(n,M(t))+1,Or(n,0,t).join("")):n},An.trimStart=function(n,t,r){
-return(n=Iu(n))&&(r||t===T)?n.replace(on,""):n&&(t=yr(t))?(n=M(n),t=I(n,M(t)),Or(n,t).join("")):n},An.truncate=function(n,t){var r=30,e="...";if(du(t))var u="separator"in t?t.separator:u,r="length"in t?ku(t.length):r,e="omission"in t?yr(t.omission):e;n=Iu(n);var i=n.length;if(Rn.test(n))var o=M(n),i=o.length;if(r>=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),hf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Xu(u.source,Iu(_n.exec(u))+"g")),
-u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},An.unescape=function(n){return(n=Iu(n))&&G.test(n)?n.replace(V,tt):n},An.uniqueId=function(n){var t=++fi;return Iu(n)+t},An.upperCase=Tf,An.upperFirst=$f,An.each=nu,An.eachRight=tu,An.first=qe,Nu(An,function(){var n={};return mt(An,function(t,r){oi.call(An.prototype,r)||(n[r]=t)}),n}(),{chain:false}),An.VERSION="4.17.11",r("bind bindKey curry curryRight partial partialRight".split(" "),function(n){
-An[n].placeholder=An}),r(["drop","take"],function(n,t){Ln.prototype[n]=function(r){r=r===T?1:Li(ku(r),0);var e=this.__filtered__&&!t?new Ln(this):this.clone();return e.__filtered__?e.__takeCount__=Ci(r,e.__takeCount__):e.__views__.push({size:Ci(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Ln.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Ln.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({
-iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Ln.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Ln.prototype[n]=function(){return this.__filtered__?new Ln(this):this[r](1)}}),Ln.prototype.compact=function(){return this.filter($u)},Ln.prototype.find=function(n){return this.filter(n).head()},Ln.prototype.findLast=function(n){return this.reverse().find(n);
-},Ln.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Ln(this):this.map(function(r){return Bt(r,n,t)})}),Ln.prototype.reject=function(n){return this.filter(au(ye(n)))},Ln.prototype.slice=function(n,t){n=ku(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Ln(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=ku(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Ln.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Ln.prototype.toArray=function(){return this.take(4294967295);
-},mt(Ln.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){var t=this.__wrapped__,o=e?[1]:arguments,f=t instanceof Ln,c=o[0],l=f||ff(t),s=function(n){return n=u.apply(An,a([n],o)),e&&h?n[0]:n};l&&r&&typeof c=="function"&&1!=c.length&&(f=l=false);var h=this.__chain__,p=!!this.__actions__.length,c=i&&!h,f=f&&!p;return!i&&l?(t=f?t:new Ln(this),t=n.apply(t,o),t.__actions__.push({
-func:Qe,args:[s],thisArg:T}),new On(t,h)):c&&f?n.apply(this,o):(t=this.thru(s),c?e?t.value()[0]:t.value():t)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ri[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(ff(u)?u:[],n)}return this[r](function(r){return t.apply(ff(r)?r:[],n)})}}),mt(Ln.prototype,function(n,t){var r=An[t];if(r){var e=r.name+"";
-(Gi[e]||(Gi[e]=[])).push({name:t,func:r})}}),Gi[Jr(T,2).name]=[{name:"wrapper",func:T}],Ln.prototype.clone=function(){var n=new Ln(this.__wrapped__);return n.__actions__=Lr(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Lr(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Lr(this.__views__),n},Ln.prototype.reverse=function(){if(this.__filtered__){var n=new Ln(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n;
-},Ln.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=ff(t),u=0>r,i=e?t.length:0;n=0;for(var o=i,f=this.__views__,c=-1,a=f.length;++c<a;){var l=f[c],s=l.size;switch(l.type){case"drop":n+=s;break;case"dropRight":o-=s;break;case"take":o=Ci(o,n+s);break;case"takeRight":n=Li(n,o-s)}}if(n={start:n,end:o},o=n.start,f=n.end,n=f-o,o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Ci(n,this.__takeCount__),!e||!u&&i==n&&l==n)return wr(t,this.__actions__);e=[];n:for(;n--&&a<l;){for(o+=r,
-u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},An.prototype.at=To,An.prototype.chain=function(){return Ye(this)},An.prototype.commit=function(){return new On(this.value(),this.__chain__)},An.prototype.next=function(){this.__values__===T&&(this.__values__=mu(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof kn;){
-var e=Fe(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Ln?(this.__actions__.length&&(n=new Ln(this)),n=n.reverse(),n.__actions__.push({func:Qe,args:[Ge],thisArg:T}),new On(n,this.__chain__)):this.thru(Ge)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,wi&&(An.prototype[wi]=Xe),
-An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this);
\ No newline at end of file
+An.isSafeInteger=function(n){return vu(n)&&-9007199254740991<=n&&9007199254740991>=n},An.isSet=pf,An.isString=ju,An.isSymbol=wu,An.isTypedArray=_f,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return yu(n)&&"[object WeakMap]"==vo(n)},An.isWeakSet=function(n){return yu(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Bi.call(n,t)},An.kebabCase=Lf,An.last=Ve,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Eu(r),u=0>u?Ui(e+u,0):Ci(u,e-1)),
+t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Uf,An.lowerFirst=Cf,An.lt=vf,An.lte=gf,An.max=function(n){return n&&n.length?xt(n,$u,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,$u)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,$u,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=qu,An.stubFalse=Vu,An.stubObject=function(){return{}},An.stubString=function(){
+return""},An.stubTrue=function(){return true},An.multiply=rc,An.nth=function(n,t){return n&&n.length?Qt(n,Eu(t)):T},An.noConflict=function(){return $n._===this&&($n._=si),this},An.noop=Pu,An.now=Go,An.pad=function(n,t,r){n=Iu(n);var e=(t=Eu(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Ii(t),r)+n+ne(Oi(t),r))},An.padEnd=function(n,t,r){n=Iu(n);var e=(t=Eu(t))?D(n):0;return t&&e<t?n+ne(t-e,r):n},An.padStart=function(n,t,r){n=Iu(n);var e=(t=Eu(t))?D(n):0;return t&&e<t?ne(t-e,r)+n:n},An.parseInt=function(n,t,r){
+return r||null==t?t=0:t&&(t=+t),Mi(Iu(n).replace(on,""),t||0)},An.random=function(n,t,r){if(r&&typeof r!="boolean"&&Oe(n,t,r)&&(t=r=T),r===T&&(typeof t=="boolean"?(r=t,t=T):typeof n=="boolean"&&(r=n,n=T)),n===T&&t===T?(n=0,t=1):(n=Au(n),t===T?(t=n,n=0):t=Au(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Ti(),Ci(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=ff(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,uo)},An.reduceRight=function(n,t,r){var e=ff(n)?s:j,u=3>arguments.length;
+return e(n,ye(t,4),r,u,io)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Eu(t),or(Iu(n),t)},An.replace=function(){var n=arguments,t=Iu(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++e<u;){var i=null==n?T:n[Me(t[e])];i===T&&(e=u,i=r),n=_u(i)?i.call(n):i}return n},An.round=ec,An.runInContext=x,An.sample=function(n){return(ff(n)?Qn:cr)(n)},An.size=function(n){if(null==n)return 0;if(su(n))return ju(n)?D(n):n.length;
+var t=vo(n);return"[object Map]"==t||"[object Set]"==t?n.size:Vt(n).length},An.snakeCase=Df,An.some=function(n,t,r){var e=ff(n)?h:pr;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.sortedIndex=function(n,t){return _r(n,t)},An.sortedIndexBy=function(n,t,r){return vr(n,t,ye(r,2))},An.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=_r(n,t);if(e<r&&lu(n[e],t))return e}return-1},An.sortedLastIndex=function(n,t){return _r(n,t,true)},An.sortedLastIndexBy=function(n,t,r){return vr(n,t,ye(r,2),true);
+},An.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=_r(n,t,true)-1;if(lu(n[r],t))return r}return-1},An.startCase=Mf,An.startsWith=function(n,t,r){return n=Iu(n),r=null==r?0:pt(Eu(r),0,n.length),t=yr(t),n.slice(r,r+t.length)==t},An.subtract=uc,An.sum=function(n){return n&&n.length?m(n,$u):0},An.sumBy=function(n,t){return n&&n.length?m(n,ye(t,2)):0},An.template=function(n,t,r){var e=An.templateSettings;r&&Oe(n,t,r)&&(t=T),n=Iu(n),t=bf({},t,e,ce),r=bf({},t.imports,e.imports,ce);var u,i,o=Wu(r),f=S(r,o),c=0;
+r=t.interpolate||jn;var a="__p+='";r=Xu((t.escape||jn).source+"|"+r.source+"|"+(r===Q?pn:jn).source+"|"+(t.evaluate||jn).source+"|$","g");var l=oi.call(t,"sourceURL")?"//# sourceURL="+(t.sourceURL+"").replace(/[\r\n]/g," ")+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(wn,z),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=oi.call(t,"variable")&&t.variable)||(a="with(obj){"+a+"}"),
+a=(i?a.replace(P,""):a).replace(Z,"$1").replace(q,"$1;"),a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=Ff(function(){return Ju(o,l+"return "+a).apply(T,f)}),t.source=a,pu(t))throw t;return t},An.times=function(n,t){if(n=Eu(n),1>n||9007199254740991<n)return[];var r=4294967295,e=Ci(n,4294967295);for(t=ye(t),n-=4294967295,e=A(e,t);++r<n;)t(r);return e},An.toFinite=Au,
+An.toInteger=Eu,An.toLength=ku,An.toLower=function(n){return Iu(n).toLowerCase()},An.toNumber=Su,An.toSafeInteger=function(n){return n?pt(Eu(n),-9007199254740991,9007199254740991):0===n?n:0},An.toString=Iu,An.toUpper=function(n){return Iu(n).toUpperCase()},An.trim=function(n,t,r){return(n=Iu(n))&&(r||t===T)?n.replace(un,""):n&&(t=yr(t))?(n=M(n),r=M(t),t=I(n,r),r=R(n,r)+1,Or(n,t,r).join("")):n},An.trimEnd=function(n,t,r){return(n=Iu(n))&&(r||t===T)?n.replace(fn,""):n&&(t=yr(t))?(n=M(n),t=R(n,M(t))+1,
+Or(n,0,t).join("")):n},An.trimStart=function(n,t,r){return(n=Iu(n))&&(r||t===T)?n.replace(on,""):n&&(t=yr(t))?(n=M(n),t=I(n,M(t)),Or(n,t).join("")):n},An.truncate=function(n,t){var r=30,e="...";if(du(t))var u="separator"in t?t.separator:u,r="length"in t?Eu(t.length):r,e="omission"in t?yr(t.omission):e;n=Iu(n);var i=n.length;if(Rn.test(n))var o=M(n),i=o.length;if(r>=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),hf(u)){if(n.slice(i).search(u)){
+var f=r;for(u.global||(u=Xu(u.source,Iu(_n.exec(u))+"g")),u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},An.unescape=function(n){return(n=Iu(n))&&G.test(n)?n.replace(V,tt):n},An.uniqueId=function(n){var t=++fi;return Iu(n)+t},An.upperCase=Tf,An.upperFirst=$f,An.each=nu,An.eachRight=tu,An.first=qe,Nu(An,function(){var n={};return mt(An,function(t,r){oi.call(An.prototype,r)||(n[r]=t)}),n}(),{chain:false
+}),An.VERSION="4.17.15",r("bind bindKey curry curryRight partial partialRight".split(" "),function(n){An[n].placeholder=An}),r(["drop","take"],function(n,t){Un.prototype[n]=function(r){r=r===T?1:Ui(Eu(r),0);var e=this.__filtered__&&!t?new Un(this):this.clone();return e.__filtered__?e.__takeCount__=Ci(r,e.__takeCount__):e.__views__.push({size:Ci(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){
+var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter($u)},Un.prototype.find=function(n){
+return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n)},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(au(ye(n)))},Un.prototype.slice=function(n,t){n=Eu(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Eu(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){
+return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295)},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||ff(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;
+return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({func:Qe,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ri[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(ff(u)?u:[],n)}return this[r](function(r){return t.apply(ff(r)?r:[],n)});
+}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+"";oi.call(Gi,e)||(Gi[e]=[]),Gi[e].push({name:t,func:r})}}),Gi[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);
+n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=ff(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c<a;){var l=o[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=Ci(n,f+s);break;case"takeRight":f=Ui(f,n-s)}}if(n={start:f,end:n},o=n.start,f=n.end,n=f-o,o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Ci(n,this.__takeCount__),!e||!u&&i==n&&l==n)return wr(t,this.__actions__);
+e=[];n:for(;n--&&a<l;){for(o+=r,u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},An.prototype.at=To,An.prototype.chain=function(){return Ye(this)},An.prototype.commit=function(){return new On(this.value(),this.__chain__)},An.prototype.next=function(){this.__values__===T&&(this.__values__=mu(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){
+for(var t,r=this;r instanceof En;){var e=Fe(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Qe,args:[Ge],thisArg:T}),new On(n,this.__chain__)):this.thru(Ge)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,
+wi&&(An.prototype[wi]=Xe),An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this);
\ No newline at end of file
index 9cdd5ce..1e8a04b 100755 (executable)
@@ -265,7 +265,8 @@ appDS2
       FLAG_FLASH_REPLACE_VF_MODULE: "FLAG_FLASH_REPLACE_VF_MODULE",
       FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT: "FLAG_FLASH_MORE_ACTIONS_BUTTON_IN_OLD_VIEW_EDIT",
       FLAG_SHOW_ORCHESTRATION_TYPE: "FLAG_SHOW_ORCHESTRATION_TYPE",
-      FLAG_2004_INSTANTIATION_TEMPLATES_POPUP : "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"
+      FLAG_2004_INSTANTIATION_TEMPLATES_POPUP : "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP",
+      FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY: "FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY"
     }
 
   };
index 673d2f6..f2301f5 100755 (executable)
@@ -1497,6 +1497,7 @@ Private metthods
                     $scope.reloadRoute();\r
                 } else {\r
                     color = FIELD.ID.COLOR_F88;\r
+                    $scope.reloadRoute();\r
                 }\r
                 $scope.callbackStyle = {\r
                     "background-color": color\r
index 1b64573..a540d16 100755 (executable)
                 viewPerPage: $scope.viewPerPage,
                 currentPage: $scope.currentPage
                        };
-                       DataService.setHasTemplate(service.hasTemplate);
+                       DataService.setIsInstantiationTemplateExists(service.isInstantiationTemplateExists);
                        sessionStorage.setItem("searchKey",JSON.stringify(searchKey));
 
                        console.log("Instantiating SDC service " + service.uuid);
index 002bcb9..e922853 100755 (executable)
@@ -75,10 +75,6 @@ var creationDialogController = function (COMPONENT, FIELD, PARAMETER, $scope, $h
             {
                 $location.path('/servicePlanning').search({serviceModelId: event.data.data.serviceModelId});
             }
-        } else if (event.data.eventId == 'showPreviousInstantiations') {
-            {
-                $location.path('/instantiationStatus').search({filterText: event.data.data.serviceModelId});
-            }
         }
         $scope.$apply();
     }
@@ -93,11 +89,14 @@ var creationDialogController = function (COMPONENT, FIELD, PARAMETER, $scope, $h
 
 
         if (!$scope.shouldShowOldPopup()) {
-            if(DataService.getHasTemplate()){
-                $scope.url = COMPONENT.INSTANTIATION_TEMPLATES_IFRAME_URL + request.modelNameVersionId;
+            let modelNameVersionId = request.modelNameVersionId ?
+                request.modelNameVersionId :
+                (DataService.getModelInfo(COMPONENT.SERVICE) ? DataService.getModelInfo(COMPONENT.SERVICE).modelNameVersionId : "");
+            if(DataService.getIsInstantiationTemplateExists()){
+                $scope.url = COMPONENT.INSTANTIATION_TEMPLATES_IFRAME_URL + modelNameVersionId;
                 window.addEventListener("message", receiveMessage, false);
             }else {
-                $scope.url = COMPONENT.SERVICE_POPUP_IFRAME_URL + request.modelNameVersionId + "&isCreate=true&r=" + Math.random();
+                $scope.url = COMPONENT.SERVICE_POPUP_IFRAME_URL + modelNameVersionId + "&isCreate=true&r=" + Math.random();
                 window.addEventListener("message", receiveMessage, false);
             }
         }
@@ -376,6 +375,7 @@ var creationDialogController = function (COMPONENT, FIELD, PARAMETER, $scope, $h
                     } else {
                         $scope.isDialogVisible = false;
                         $scope.popup.isVisible = false;
+                        runCallback(response);
                     }
                 }
             });
index 10c4277..1e539ac 100755 (executable)
@@ -320,11 +320,11 @@ var DataService = function($log, DataService) {
                setOwningEntityProperties: function (properties) {
                                _this.owningEntityProperties = properties;
                },
-               getHasTemplate: function () {
-                               return _this.hasTemplate;
+               getIsInstantiationTemplateExists: function () {
+                               return _this.isInstantiationTemplateExists;
                },
-               setHasTemplate: function (hasTemplate) {
-                               _this.hasTemplate = hasTemplate;
+               setIsInstantiationTemplateExists: function (isInstantiationTemplateExists) {
+                               _this.isInstantiationTemplateExists = isInstantiationTemplateExists;
                }
        };
 };
index f9668c9..06ef5d5 100644 (file)
@@ -33,8 +33,10 @@ import org.onap.vid.model.SubscriberList;
 import org.onap.vid.roles.EcompRole;
 import org.onap.vid.roles.Role;
 import org.onap.vid.roles.RoleValidator;
+import org.onap.vid.roles.RoleValidatorFactory;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
 
 public class SubscriberFilteredResultsTest {
 
@@ -89,9 +91,7 @@ public class SubscriberFilteredResultsTest {
     }
 
     private void prepareRoleValidator() {
-        ArrayList<Role> list = new ArrayList<>();
-        list.add(new Role(EcompRole.READ, "a", "a", "a"));
-       roleValidator = RoleValidator.by(list);
+        roleValidator = mock(RoleValidator.class);
     }
 
     private void prepareSubscriberList() throws IOException {
diff --git a/vid-app-common/src/test/java/org/onap/vid/bl/AaiServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/bl/AaiServiceTest.java
deleted file mode 100644 (file)
index 1d45565..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * VID
- * ================================================================================
- * Copyright (C) 2017 - 2019 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.onap.vid.bl;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.arrayWithSize;
-import static org.hamcrest.Matchers.equalTo;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.onap.vid.aai.AaiClientInterface;
-import org.onap.vid.aai.AaiResponse;
-import org.onap.vid.aai.model.AaiGetPnfResponse;
-import org.onap.vid.aai.model.AaiGetPnfs.Pnf;
-import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
-import org.onap.vid.aai.model.LogicalLinkResponse;
-import org.onap.vid.aai.model.Relationship;
-import org.onap.vid.aai.model.RelationshipData;
-import org.onap.vid.aai.model.RelationshipList;
-import org.onap.vid.aai.model.ServiceRelationships;
-import org.onap.vid.roles.Role;
-import org.onap.vid.roles.RoleValidator;
-import org.onap.vid.services.AaiServiceImpl;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-public class AaiServiceTest {
-
-    @InjectMocks
-    private AaiServiceImpl aaiService;
-
-    @Mock
-    private AaiClientInterface aaiClientInterface;
-
-
-
-    @BeforeMethod
-    public void initMocks(){
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void testGetSpecificPnf(){
-        Pnf pnf = Pnf.builder().withPnfId("11111").build();
-        AaiResponse<Pnf> aaiResponse = new AaiResponse<>(pnf, "aaaa", 200);
-        Mockito.doReturn(aaiResponse).when(aaiClientInterface).getSpecificPnf(Mockito.anyString());
-        AaiResponse<Pnf> specificPnf = aaiService.getSpecificPnf("1345667");
-        assertNotNull(specificPnf);
-        pnf = specificPnf.getT();
-        assertNotNull(pnf);
-        assertEquals("11111",pnf.getPnfId());
-        assertEquals("aaaa",specificPnf.getErrorMessage());
-        assertEquals(200,specificPnf.getHttpCode());
-    }
-
-    @Test
-    public void testPnfByRegion(){
-        AaiGetPnfResponse aaiGetPnfResponse = new AaiGetPnfResponse();
-        AaiResponse<AaiGetPnfResponse> aaiResponse = new AaiResponse<>(aaiGetPnfResponse, "", 200);
-        Mockito.doReturn(aaiResponse).when(aaiClientInterface).getPNFData(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
-        AaiResponse<AaiGetPnfResponse> aaiGetPnfResponseWrapper = aaiService.getPNFData("1345667", "1345667", "1345667", "1345667", "1345667", "1345667", "1345667");
-        assertNotNull(aaiGetPnfResponseWrapper);
-        aaiGetPnfResponse = aaiGetPnfResponseWrapper.getT();
-        assertNotNull(aaiGetPnfResponse);
-    }
-
-    @Test
-    public void testGetAssociatedPnfs(){
-        ServiceRelationships serviceRelationships = createServiceRelationships();
-        AaiResponse<ServiceRelationships> aaiResponse = new AaiResponse<>(serviceRelationships, null, 200);
-        Mockito.doReturn(aaiResponse).when(aaiClientInterface).getServiceInstance(Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
-
-        LogicalLinkResponse logicalLinkResponse = createLogicalLinkResponse();
-        AaiResponse<LogicalLinkResponse> aaiResponse1 = new AaiResponse<>(logicalLinkResponse, null, 200);
-        Mockito.doReturn(aaiResponse1).when(aaiClientInterface).getLogicalLink("SANITY6758cce9%3ALAG1992%7CSANITY6785cce9%3ALAG1961");
-
-        List<String> pnfList = aaiService.getServiceInstanceAssociatedPnfs("123", "456", "789");
-        assertNotNull(pnfList);
-        assertEquals(1, pnfList.size());
-        assertEquals("SANITY6785cce9", pnfList.get(0));
-    }
-
-    private ServiceRelationships createServiceRelationships() {
-        ServiceRelationships serviceRelationships = new ServiceRelationships();
-        serviceRelationships.setServiceInstanceName("test service");
-
-        RelationshipData logicalLinksRelationshipData = new RelationshipData();
-        logicalLinksRelationshipData.setRelationshipKey("logical-link.link-name");
-        logicalLinksRelationshipData.setRelationshipValue("SANITY6758cce9:LAG1992|SANITY6785cce9:LAG1961");
-
-        Relationship logicalLinksRelationship = new Relationship();
-        logicalLinksRelationship.setRelatedTo("logical-link");
-        logicalLinksRelationship.setRelationDataList(Arrays.asList(logicalLinksRelationshipData));
-
-        RelationshipList logicalLinksRelationshipsList = new RelationshipList();
-        logicalLinksRelationshipsList.setRelationship(Arrays.asList(logicalLinksRelationship));
-
-        serviceRelationships.setRelationshipList(logicalLinksRelationshipsList);
-        return serviceRelationships;
-    }
-
-    private LogicalLinkResponse createLogicalLinkResponse() {
-        LogicalLinkResponse logicalLinkResponse = new LogicalLinkResponse();
-        logicalLinkResponse.setLinkName("SANITY6758cce9:LAG1992|SANITY6785cce9:LAG1961");
-
-        RelationshipData lagInterfaceRelationshipData = new RelationshipData();
-        lagInterfaceRelationshipData.setRelationshipKey("pnf.pnf-name");
-        lagInterfaceRelationshipData.setRelationshipValue("SANITY6785cce9");
-
-        Relationship lagInterfaceRelationship = new Relationship();
-        lagInterfaceRelationship.setRelatedTo("lag-interface");
-        lagInterfaceRelationship.setRelationDataList(Arrays.asList(lagInterfaceRelationshipData));
-
-        RelationshipList lagInterfaceRelationshipsList = new RelationshipList();
-        lagInterfaceRelationshipsList.setRelationship(Arrays.asList(lagInterfaceRelationship));
-
-        logicalLinkResponse.setRelationshipList(lagInterfaceRelationshipsList);
-
-        return logicalLinkResponse;
-    }
-
-    @DataProvider
-    public static Object[][] getTenantsData() {
-        return new Object[][] {
-                {"customer1", "serviceType1", "tenant1", "customer1", "serviceType1", "tenant1", "id-1", true},
-                {"customer1", "serviceType1", "TeNant1", "customer1", "serviceType1", "tenant1", "id-1", true},
-                {"customer1", "serviceType1", "TENANT1", "customer1", "serviceType1", "tenant1", "id-1", true},
-                {"customer1", "serviceType1", "tenant2", "customer1", "serviceType1", "tenant1", "tenant2", false},
-                {"customer1", "serviceType1", null, "customer1", "serviceType1", "tenant1", "tenant2", true},
-                {"customer2", "serviceType1", "tenant1", "customer1", "serviceType1", "tenant1", "id-1", false},
-                {"customer1", "serviceType2", "tenant1", "customer1", "serviceType1", "tenant1", "id-1", false},
-                {"customer2", "serviceType1", null, "customer1", "serviceType1", "tenant1", "id-1", false},
-                {"customer1", "serviceType2", null, "customer1", "serviceType1", "tenant1", "id-1", false},
-        };
-    }
-
-    @Test(dataProvider = "getTenantsData")
-    public void testGetTenants(String userGlobalCustomerId, String userServiceType, String userTenantName, String serviceGlobalCustomerId,
-                               String serviceServiceType, String serviceTenantName, String serviceTenantId, boolean expectedIsPermitted) {
-        GetTenantsResponse[] getTenantsResponses = new GetTenantsResponse[] {new GetTenantsResponse(null, null, serviceTenantName, serviceTenantId, expectedIsPermitted)};
-        AaiResponse<GetTenantsResponse[]> aaiResponse = new AaiResponse<>(getTenantsResponses, null, 200);
-        Mockito.doReturn(aaiResponse).when(aaiClientInterface).getTenants(serviceGlobalCustomerId, serviceServiceType);
-        Role role = new Role(null, userGlobalCustomerId, userServiceType, userTenantName);
-        RoleValidator roleValidator = RoleValidator.by(Collections.singletonList(role));
-        AaiResponse<GetTenantsResponse[]> actualTenants = aaiService.getTenants(serviceGlobalCustomerId, serviceServiceType, roleValidator);
-
-        assertThat(actualTenants.getT(), arrayWithSize(1));
-        assertThat(actualTenants.getT()[0].tenantName, equalTo(serviceTenantName));
-        //assertThat(actualTenants.getT()[0].isPermitted, equalTo(expectedIsPermitted));
-    }
-}
index c4f7886..3f2bf73 100644 (file)
@@ -31,12 +31,32 @@ import org.onap.vid.aai.util.SystemPropertyHelper;
 import org.onap.vid.dal.AsyncInstantiationRepository;
 import org.onap.vid.job.JobAdapter;
 import org.onap.vid.job.JobsBrokerService;
-import org.onap.vid.job.command.*;
+import org.onap.vid.job.command.ALaCarteServiceCommand;
+import org.onap.vid.job.command.CommandUtils;
+import org.onap.vid.job.command.InProgressStatusService;
+import org.onap.vid.job.command.InstanceGroupCommand;
+import org.onap.vid.job.command.InstanceGroupMemberCommand;
+import org.onap.vid.job.command.JobCommandFactory;
+import org.onap.vid.job.command.MacroServiceCommand;
+import org.onap.vid.job.command.MsoRequestBuilder;
+import org.onap.vid.job.command.MsoResultHandlerService;
+import org.onap.vid.job.command.NetworkCommand;
+import org.onap.vid.job.command.VfmoduleCommand;
+import org.onap.vid.job.command.VnfCommand;
+import org.onap.vid.job.command.VolumeGroupCommand;
+import org.onap.vid.job.command.WatchChildrenJobsBL;
 import org.onap.vid.job.impl.JobAdapterImpl;
 import org.onap.vid.job.impl.JobWorker;
 import org.onap.vid.job.impl.JobsBrokerServiceInDatabaseImpl;
+import org.onap.vid.model.ModelUtil;
 import org.onap.vid.mso.RestMsoImplementation;
-import org.onap.vid.services.*;
+import org.onap.vid.services.AsyncInstantiationBusinessLogic;
+import org.onap.vid.services.AsyncInstantiationBusinessLogicImpl;
+import org.onap.vid.services.AuditService;
+import org.onap.vid.services.AuditServiceImpl;
+import org.onap.vid.services.CloudOwnerService;
+import org.onap.vid.services.InstantiationTemplatesService;
+import org.onap.vid.services.VersionService;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
@@ -130,6 +150,18 @@ public class JobCommandsConfigWithMockedMso {
         return new AsyncInstantiationBusinessLogicImpl(jobAdapter, jobsBrokerService, sessionFactory, aaiClient, featureManager, cloudOwnerService, asyncInstantiationRepository, auditService);
     }
 
+    @Bean
+    public ModelUtil modelUtil() {return new ModelUtil();}
+
+    @Bean
+    public InstantiationTemplatesService instantiationTemplatesService(
+        ModelUtil modelUtil,
+        AsyncInstantiationRepository asyncInstantiationRepository,
+        FeatureManager featureManager
+        ) {
+        return new InstantiationTemplatesService(modelUtil, asyncInstantiationRepository, featureManager);
+    };
+
 
     @Bean
     @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
index 5211023..202263c 100644 (file)
@@ -23,11 +23,13 @@ package org.onap.vid.controller;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -68,8 +70,11 @@ import org.onap.vid.aai.model.PortDetailsTranslator.PortDetailsOk;
 import org.onap.vid.aai.util.AAIRestInterface;
 import org.onap.vid.model.VersionByInvariantIdsRequest;
 import org.onap.vid.properties.Features;
+import org.onap.vid.roles.AlwaysValidRoleValidator;
 import org.onap.vid.roles.RoleProvider;
-import org.onap.vid.roles.RoleValidatorByRoles;
+import org.onap.vid.roles.RoleValidator;
+import org.onap.vid.roles.RoleValidatorBySubscriberAndServiceType;
+import org.onap.vid.roles.RoleValidatorFactory;
 import org.onap.vid.services.AaiService;
 import org.onap.vid.utils.SystemPropertiesWrapper;
 import org.onap.vid.utils.Unchecked;
@@ -92,6 +97,8 @@ public class AaiControllerTest {
     @Mock
     private RoleProvider roleProvider;
     @Mock
+    private RoleValidator roleValidator;
+    @Mock
     private SystemPropertiesWrapper systemPropertiesWrapper;
     @Mock
     private FeatureManager featureManager;
@@ -103,6 +110,7 @@ public class AaiControllerTest {
     public void setUp() {
         aaiController = new AaiController(aaiService, aaiRestInterface, roleProvider, systemPropertiesWrapper,
             featureManager);
+        when(roleProvider.getUserRolesValidator(any())).thenReturn(roleValidator);
         mockMvc = MockMvcBuilders.standaloneSetup(aaiController).build();
     }
 
@@ -408,7 +416,7 @@ public class AaiControllerTest {
         String okResponseBody = "OK_RESPONSE";
         AaiResponse<String> aaiResponse = new AaiResponse<>(okResponseBody, "", HttpStatus.OK.value());
         given(featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH)).willReturn(isFeatureActive);
-        given(aaiService.getSubscriberData(eq(subscriberId), isA(RoleValidatorByRoles.class),
+        given(aaiService.getSubscriberData(eq(subscriberId), isA(RoleValidator.class),
             eq(isFeatureActive && omitServiceInstances)))
             .willReturn(aaiResponse);
 
@@ -479,7 +487,7 @@ public class AaiControllerTest {
         String okResponseBody = "OK_RESPONSE";
         AaiResponse<String> aaiResponse = new AaiResponse<>(okResponseBody, "", HttpStatus.OK.value());
         given(featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH)).willReturn(isFeatureActive);
-        given(aaiService.getSubscriberData(eq(subscriberId), isA(RoleValidatorByRoles.class),
+        given(aaiService.getSubscriberData(eq(subscriberId), isA(RoleValidator.class),
             eq(isFeatureActive && omitServiceInstances)))
             .willReturn(aaiResponse);
 
index f0d8409..6f584ed 100644 (file)
@@ -66,7 +66,7 @@ public class LoggerControllerTest {
 
     @Test
     public void shouldThrowNotAuthorizedException_whenUserIsNotAuthorizedToGetLogs() throws Exception {
-        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1"));
+        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1", "owningEntityId"));
 
         given(provider.getUserRoles(argThat(req -> req.getRequestedSessionId().equals("id1")))).willReturn(list);
         given(provider.userPermissionIsReadLogs(list)).willReturn(false);
@@ -80,7 +80,7 @@ public class LoggerControllerTest {
 
     @Test
     public void shouldReturnLastAndOneBeforeLogLines_whenLimitIs2() throws Exception {
-        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1"));
+        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1", "owningEntityId"));
 
         given(provider.getUserRoles(argThat(req -> req.getRequestedSessionId().equals("id1")))).willReturn(list);
         given(provider.userPermissionIsReadLogs(list)).willReturn(true);
@@ -96,7 +96,7 @@ public class LoggerControllerTest {
 
     @Test
     public void shouldReturnEmptyString_whenLogFileIsEmpty() throws Exception {
-        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1"));
+        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1", "owningEntityId"));
 
         given(provider.getUserRoles(argThat(req -> req.getRequestedSessionId().equals("id1")))).willReturn(list);
         given(provider.userPermissionIsReadLogs(list)).willReturn(true);
@@ -111,7 +111,7 @@ public class LoggerControllerTest {
 
     @Test
     public void shouldReturnEmptyString_whenDebugLogFileIsEmpty() throws Exception {
-        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1"));
+        List<Role> list = ImmutableList.of(new Role(EcompRole.READ, "subName1", "servType1", "tenant1", "owningEntityId"));
 
         given(provider.getUserRoles(argThat(req -> req.getRequestedSessionId().equals("id1")))).willReturn(list);
         given(provider.userPermissionIsReadLogs(list)).willReturn(true);
index ac3da50..3b7dbfb 100644 (file)
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.when;
 
 import org.jetbrains.annotations.NotNull;
 import org.onap.vid.aai.model.Permissions;
+import org.onap.vid.roles.PermissionPropertiesSubscriberAndServiceType;
 import org.onap.vid.roles.RoleProvider;
 import org.onap.vid.roles.RoleValidator;
 import org.springframework.mock.web.MockHttpServletRequest;
@@ -53,7 +54,7 @@ public class ServicePermissionsTest {
         RoleProvider roleProvider = mock(RoleProvider.class);
         RoleValidator roleValidator = mock(RoleValidator.class);
         when(roleProvider.getUserRolesValidator(any())).thenReturn(roleValidator);
-        when(roleValidator.isServicePermitted(subscriberId, serviceType)).thenReturn(expected);
+        when(roleValidator.isServicePermitted(new PermissionPropertiesSubscriberAndServiceType(subscriberId, serviceType))).thenReturn(expected);
 
         AaiController2 aaiController2 = new AaiController2(null, roleProvider, null, null);
 
index 484f4a0..da91edb 100644 (file)
 package org.onap.vid.controller;
 
 
+import static java.util.stream.Collectors.toMap;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.not;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.then;
+import static org.mockito.Mockito.times;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.IntStream;
+import javax.ws.rs.core.MediaType;
 import org.apache.log4j.BasicConfigurator;
 import org.junit.Assert;
 import org.junit.Before;
@@ -35,35 +53,24 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.onap.vid.asdc.AsdcCatalogException;
 import org.onap.vid.asdc.beans.SecureServices;
 import org.onap.vid.asdc.beans.Service;
-import org.onap.vid.model.*;
+import org.onap.vid.model.CR;
+import org.onap.vid.model.Network;
+import org.onap.vid.model.Node;
 import org.onap.vid.model.PombaInstance.PombaRequest;
 import org.onap.vid.model.PombaInstance.ServiceInstance;
+import org.onap.vid.model.ServiceModel;
+import org.onap.vid.model.ServiceProxy;
+import org.onap.vid.model.VNF;
+import org.onap.vid.model.VfModule;
+import org.onap.vid.model.VolumeGroup;
 import org.onap.vid.roles.RoleProvider;
 import org.onap.vid.services.AaiService;
+import org.onap.vid.services.InstantiationTemplatesService;
 import org.onap.vid.services.PombaService;
 import org.onap.vid.services.VidService;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import javax.ws.rs.core.MediaType;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.stream.IntStream;
-
-import static java.util.stream.Collectors.toMap;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.Matchers.not;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.then;
-import static org.mockito.Mockito.times;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
 @RunWith(MockitoJUnitRunner.class)
 public class VidControllerTest {
 
@@ -79,6 +86,8 @@ public class VidControllerTest {
     private RoleProvider roleProvider;
     @Mock
     private PombaService pombaService;
+    @Mock
+    private InstantiationTemplatesService instantiationTemplatesService;
 
     private VidController vidController;
     private MockMvc mockMvc;
@@ -90,7 +99,7 @@ public class VidControllerTest {
 
     @Before
     public void setUp() {
-        vidController = new VidController(vidService, aaiService, roleProvider, pombaService);
+        vidController = new VidController(vidService, aaiService, roleProvider, pombaService, instantiationTemplatesService);
         BasicConfigurator.configure();
         mockMvc = MockMvcBuilders.standaloneSetup(vidController).build();
         objectMapper = new ObjectMapper();
@@ -102,12 +111,17 @@ public class VidControllerTest {
 
     @Test
     public void getServices_shouldReturnService_whenServiceExists() throws Exception {
-        List<Service> services = ImmutableList.of(createService(uuid1, 1), createService(uuid2, 2), createService(uuid3, 3));
+        List<Service> services1 = ImmutableList.of(createService(uuid1, 1), createService(uuid2, 2), createService(uuid3, 3));
+        List<Service> services2 = ImmutableList.of(createService(uuid1, 4), createService(uuid2, 5), createService(uuid3, 6));
+
+        given(aaiService.getServicesByDistributionStatus())
+            .willReturn(services1);
 
-        given(aaiService.getServicesByDistributionStatus()).willReturn(services);
+        given(instantiationTemplatesService.setOnEachServiceIsTemplateExists(services1))
+            .willReturn(services2);
 
         SecureServices secureServices = new SecureServices();
-        secureServices.setServices(services);
+        secureServices.setServices(services2);
         secureServices.setReadOnly(false);
 
         mockMvc.perform(get(REST_MODELS_SERVICES)
index db856d7..b916347 100644 (file)
@@ -279,7 +279,7 @@ public class ResourceCommandTest {
                     convertToMap(networks),
                     convertToMap(vnfGroups),
                     null,
-                    null, false, 1, false,false,null, null, null, null, null, null, null);
+                    null, false, 1, false,false,null, null, null, null, null, null, null, null);
         }
 
         public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) {
@@ -298,11 +298,11 @@ public class ResourceCommandTest {
 
         static InstanceGroup createGroup(List<InstanceGroupMember> groupMembers, Action action) {
             return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null,
-                null);
+                null, null);
         }
 
         static InstanceGroupMember createMember(Action action) {
-            return new InstanceGroupMember(null, action.toString(), null, null, null, null);
+            return new InstanceGroupMember(null, action.toString(), null, null, null, null, null);
         }
 
         static Vnf createVnf(List<VfModule> vfModules, Action action) {
@@ -310,22 +310,22 @@ public class ResourceCommandTest {
             vfModulesMap.put("abc",convertToMap(vfModules));
 
             return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null,
-                null);
+                null, null);
         }
 
         static Vnf createVnf(Action action) {
             return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null,
-                null);
+                null, null);
         }
 
         static VfModule createVfModule(Action action) {
             return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null,
-                false, false, null, null, null, null, null, null, null);
+                false, false, null, null, null, null, null, null, null, null);
         }
 
         static Network createNetwork(Action action) {
             return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null,
-                null);
+                null, null);
         }
     }
 
diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt b/vid-app-common/src/test/java/org/onap/vid/job/command/VnfCommandTest.kt
new file mode 100644 (file)
index 0000000..660abe4
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2020 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.onap.vid.job.command
+
+import net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.core.AllOf.allOf
+import org.mockito.Answers
+import org.mockito.InjectMocks
+import org.mockito.Mock
+import org.onap.vid.job.JobAdapter
+import org.onap.vid.job.JobsBrokerService
+import org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator
+import org.onap.vid.job.impl.JobSharedData
+import org.onap.vid.model.Action
+import org.onap.vid.mso.RestMsoImplementation
+import org.onap.vid.properties.Features
+import org.onap.vid.services.AsyncInstantiationBusinessLogic
+import org.onap.vid.testUtils.TestUtils
+import org.onap.vid.testUtils.TestUtils.initMockitoMocks
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+import org.togglz.core.manager.FeatureManager
+import org.mockito.Mockito.`when` as _when
+
+class VnfCommandTest {
+
+    @Mock lateinit var asyncInstantiationBL: AsyncInstantiationBusinessLogic
+    @Mock lateinit var restMso: RestMsoImplementation
+    @Mock lateinit var msoRequestBuilder: MsoRequestBuilder
+    @Mock lateinit var msoResultHandlerService: MsoResultHandlerService
+    @Mock lateinit var inProgressStatusService:InProgressStatusService
+    @Mock lateinit var watchChildrenJobsBL: WatchChildrenJobsBL
+    @Mock lateinit var jobsBrokerService: JobsBrokerService
+    @Mock lateinit var jobAdapter: JobAdapter
+    @Mock lateinit var featureManager: FeatureManager
+
+    @Mock lateinit var jobSharedData: JobSharedData
+    @Mock(answer = Answers.RETURNS_MOCKS) lateinit var vnfJobRequest: org.onap.vid.model.serviceInstantiation.Vnf
+
+    @InjectMocks lateinit var vnfCommand: VnfCommand;
+
+    @BeforeMethod
+    fun initMocks() {
+        initMockitoMocks(this)
+    }
+
+    @Test(dataProvider = "trueAndFalse", dataProviderClass = TestUtils::class)
+    fun `childVfModuleWithVnfRegionAndTenant -- given vfmodule -- tenant and region are copied from vnf`(featureToggleOn: Boolean) {
+
+        val vfModule = FakeResourceCreator.createVfModule(Action.Create)
+                        .cloneWith("vfmodule-lcp-cloud-region-id", "vfmodule-tenant-id")
+
+        _when(featureManager.isActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)).thenReturn(featureToggleOn)
+
+        _when(vnfJobRequest.lcpCloudRegionId).thenReturn("vnf-lcp-cloud-region-id")
+        _when(vnfJobRequest.tenantId).thenReturn("vnf-tenant-id")
+        _when(jobSharedData.request).thenReturn(vnfJobRequest)
+
+        vnfCommand.init(jobSharedData, mapOf())
+
+        val expectedSource = if (featureToggleOn) "vnf" else "vfmodule"
+
+        assertThat(vnfCommand.childVfModuleWithVnfRegionAndTenant(vfModule),
+                allOf(
+                        jsonPartEquals("lcpCloudRegionId", "${expectedSource}-lcp-cloud-region-id"),
+                        jsonPartEquals("tenantId", "${expectedSource}-tenant-id")
+                )
+        )
+    }
+
+}
index cd4045b..642adb3 100644 (file)
@@ -59,6 +59,7 @@ import static org.onap.vid.job.Job.JobStatus.STOPPED;
 import static org.onap.vid.job.impl.JobSchedulerInitializer.WORKERS_TOPICS;
 import static org.onap.vid.model.JobAuditStatus.SourceStatus.VID;
 import static org.onap.vid.testUtils.TestUtils.readJsonResourceFileAsObject;
+import static org.testng.Assert.assertNull;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
@@ -119,6 +120,7 @@ import org.onap.vid.properties.Features;
 import org.onap.vid.services.AsyncInstantiationBaseTest;
 import org.onap.vid.services.AsyncInstantiationBusinessLogic;
 import org.onap.vid.services.AuditService;
+import org.onap.vid.services.InstantiationTemplatesService;
 import org.onap.vid.services.VersionService;
 import org.onap.vid.testUtils.TestUtils;
 import org.onap.vid.utils.DaoUtils;
@@ -172,6 +174,9 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
     @Inject
     private CommandUtils commandUtils;
 
+    @Inject
+    private InstantiationTemplatesService instantiationTemplates;
+
     @BeforeClass
     void initServicesInfoService() {
         createInstanceParamsMaps();
@@ -189,7 +194,12 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
     void defineMocks() {
         Mockito.reset(restMso);
         Mockito.reset(aaiClient);
+        Mockito.reset(commandUtils);
         mockAaiClientAnyNameFree();
+
+        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true);
+        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
+        when(featureManager.isActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)).thenReturn(true);
     }
 
     @Test
@@ -371,9 +381,7 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
 
            * not looking on audit (yet)
         */
-        reset(restMso);
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true);
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(false);
+        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(false); // this makes the test pass without mocking the vfModules
         final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
         final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
         final String VNF_REQUEST_ID = UUID.randomUUID().toString();
@@ -416,8 +424,6 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
 
 
         String msoVnfStatus = COMPLETE_STR;
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true);
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
         final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
         final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
         final String VNF_REQUEST_ID = UUID.randomUUID().toString();
@@ -431,7 +437,6 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
         //push alacarte with 1 vnf, verify STATUS pending
         UUID uuid = pushALaCarteWithVnf();
         singleServicesAndAssertStatus(JobStatus.PENDING, uuid);
-        reset(restMso);
 
         /*---------- service -----------*/
 
@@ -514,8 +519,6 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
         NetworkDetails networkDetails1 = new NetworkDetails("LukaDoncic", "1");
         NetworkDetails networkDetails2 = new NetworkDetails("KevinDurant", "2");
 
-        reset(restMso);
-
         /*---------- service -----------*/
 
         //mock mso to answer 200 of create service instance request, verify STATUS in progress
@@ -1014,8 +1017,6 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
         JobStatus expectedJobStatus,
         int getStatusCounter) throws IOException, AsdcCatalogException {
 
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
-        reset(commandUtils);
         when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "f8360508-3f17-4414-a2ed-6bc71161e8db")).thenReturn(true);
         when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "25284168-24bb-4698-8cb4-3f509146eca5")).thenReturn(false);
 
@@ -1266,7 +1267,6 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
                 asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR),
                 asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
 
-        when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
         enableAddCloudOwnerOnMsoRequest();
 
 
@@ -1309,4 +1309,41 @@ public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTes
         return readJsonResourceFileAsObject("/payload_jsons/vfmodule/upgrade_vfmodule_e2e__fe_input_cypress.json", ServiceInstantiation.class);
     }
 
+    @Test
+    public void deployService_failIt_retryDeploy_getRetryAsTemplate_makeSureFalsyIsFailedInTemplate() {
+
+        final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
+
+        //push alacarte with 1 vnf, verify STATUS pending
+        UUID uuid = pushALaCarteWithVnf();
+        singleServicesAndAssertStatus(JobStatus.PENDING, uuid);
+
+        //mock mso to answer 200 of create service instance request, verify STATUS in progress
+        when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn(
+            createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID));
+
+        //mock mso to answer FAILED for service instance create
+        final RestObject<AsyncRequestStatus> failedResponse = asyncRequestStatusResponseAsRestObject(FAILED_STR);
+        final String failureDescription = "Some deep failure";
+        failedResponse.get().request.requestStatus.setStatusMessage(failureDescription);
+        when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).
+            thenReturn(failedResponse);
+
+        //Wait till job failed
+        processJobsCountTimesAndAssertStatus(uuid, 3, FAILED);
+
+        //make sure retry request jas isFailed = true, and status message is with failureDescription
+        ServiceInstantiation retryRequest = asyncInstantiationBL.getBulkForRetry(uuid);
+        assertTrue(retryRequest.getIsFailed());
+        assertEquals(failureDescription, retryRequest.getStatusMessage());
+
+        //deploy retry job and it's template
+        UUID retryUuid = asyncInstantiationBL.pushBulkJob(retryRequest, USER_ID).get(0);
+        ServiceInstantiation templateOfRetry = instantiationTemplates.getJobRequestAsTemplate(retryUuid);
+
+        //make sure the template request has isFailed = false, and no status message
+        assertFalse(templateOfRetry.getIsFailed());
+        assertNull(templateOfRetry.getStatusMessage());
+    }
+
 }
index 5168a5c..b777375 100644 (file)
 
 package org.onap.vid.model;
 
-import org.junit.Test;
+import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanConstructor;
+import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanEqualsFor;
+import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanHashCodeFor;
+import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonNodeAbsent;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals;
+import static org.apache.commons.lang3.ArrayUtils.toArray;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.testng.annotations.Test;
 
 public class ServiceInstanceSearchResultTest {
 
-    private ServiceInstanceSearchResult createTestSubject() {
-        return new ServiceInstanceSearchResult();
-    }
-
-    @Test
-    public void testGetServiceInstanceId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getServiceInstanceId();
-    }
-
-    @Test
-    public void testSetServiceInstanceId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String serviceInstanceId = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setServiceInstanceId(serviceInstanceId);
-    }
-
-    @Test
-    public void testGetGlobalCustomerId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getGlobalCustomerId();
-    }
-
-    @Test
-    public void testSetGlobalCustomerId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String globalCustomerId = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setGlobalCustomerId(globalCustomerId);
-    }
-
-    @Test
-    public void testGetServiceType() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getServiceType();
-    }
-
-    @Test
-    public void testSetServiceType() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String serviceType = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setServiceType(serviceType);
-    }
-
-    @Test
-    public void testGetServiceInstanceName() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getServiceInstanceName();
-    }
-
-    @Test
-    public void testSetServiceInstanceName() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String serviceInstanceName = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setServiceInstanceName(serviceInstanceName);
-    }
-
-    @Test
-    public void testGetSubscriberName() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getSubscriberName();
-    }
-
-    @Test
-    public void testSetSubscriberName() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String subscriberName = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setSubscriberName(subscriberName);
-    }
-
     @Test
-    public void testGetAaiModelInvariantId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getAaiModelInvariantId();
-    }
-
-    @Test
-    public void testSetAaiModelInvariantId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String aaiModelInvariantId = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setAaiModelInvariantId(aaiModelInvariantId);
-    }
-
-    @Test
-    public void testGetAaiModelVersionId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getAaiModelVersionId();
+    public void shouldHaveValidGettersAndSetters() {
+        assertThat(ServiceInstanceSearchResult.class, hasValidGettersAndSetters());
     }
 
     @Test
-    public void testSetAaiModelVersionId() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        String aaiModelVersionId = "";
-
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setAaiModelVersionId(aaiModelVersionId);
-    }
-
-    @Test
-    public void testGetIsPermitted() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        boolean result;
-
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.getIsPermitted();
+    public void shouldHaveValidConstructor() {
+        assertThat(ServiceInstanceSearchResult.class, hasValidBeanConstructor());
     }
 
     @Test
-    public void testSetIsPermitted() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        boolean isPermitted = false;
+    public void shouldHaveValidEqualsAndHashCode() {
+        String[] propertiesToEqualBy = toArray("serviceInstanceId");
 
-        // default test
-        testSubject = createTestSubject();
-        testSubject.setIsPermitted(isPermitted);
+        assertThat(ServiceInstanceSearchResult.class, allOf(
+            hasValidBeanHashCodeFor(propertiesToEqualBy),
+            hasValidBeanEqualsFor(propertiesToEqualBy))
+        );
     }
 
     @Test
-    public void testEquals() throws Exception {
-        ServiceInstanceSearchResult testSubject;
-        Object other = null;
-        boolean result;
+    public void subscriberId_shouldBeSerializedAsGlobalCustomerId() {
+        ServiceInstanceSearchResult underTest = new ServiceInstanceSearchResult();
+        underTest.setSubscriberId("example");
 
-        // default test
-        testSubject = createTestSubject();
-        result = testSubject.equals(other);
+        assertThat(underTest, jsonPartEquals("globalCustomerId", "example"));
+        assertThat(underTest, jsonNodeAbsent("subscriberId"));
     }
 
 }
index b5d2816..f0c96b8 100644 (file)
@@ -38,6 +38,7 @@ import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.lang.reflect.InvocationTargetException;
+import java.util.List;
 import java.util.Map;
 import org.apache.commons.beanutils.PropertyUtils;
 import org.onap.vid.model.VidNotions;
@@ -45,6 +46,7 @@ import org.onap.vid.model.VidNotions.InstantiationType;
 import org.onap.vid.model.VidNotions.InstantiationUI;
 import org.onap.vid.model.VidNotions.ModelCategory;
 import org.onap.vid.mso.model.ModelInfo;
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue;
 import org.testng.annotations.Test;
 
 public class InstantiationModelSerializationTest {
@@ -92,7 +94,8 @@ public class InstantiationModelSerializationTest {
             new VidNotions(InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED,
                 ModelCategory.INFRASTRUCTURE_VPN,
                 InstantiationUI.INFRASTRUCTURE_VPN,
-                InstantiationType.Macro)
+                InstantiationType.Macro),
+            "originalName"
         );
 
         verifySerializationAndDeserialization(serviceInstantiation);
@@ -117,7 +120,8 @@ public class InstantiationModelSerializationTest {
             "trackById",
             true,
             "statusMessage",
-            5);
+            5,
+            "originalName");
 
         verifySerializationAndDeserialization(vnf);
     }
@@ -125,10 +129,10 @@ public class InstantiationModelSerializationTest {
     @Test
     public void serializeAndDeserializeVfModule() throws Exception {
 
-        ImmutableMap<String, String> supplementaryParams = ImmutableMap.of(
-            "uno", "1",
-            "dos", "2",
-            "tres", "3"
+        List<UserParamNameAndValue> supplementaryParams = ImmutableList.of(
+            new UserParamNameAndValue("uno", "1"),
+            new UserParamNameAndValue("dos", "2"),
+            new UserParamNameAndValue("tres", "3")
         );
 
         VfModule vfModule = new VfModule(
@@ -149,7 +153,8 @@ public class InstantiationModelSerializationTest {
             "statusMessage",
             true,
             true,
-            1);
+            1,
+            "originalName");
 
         verifySerializationAndDeserialization(vfModule);
     }
@@ -162,7 +167,7 @@ public class InstantiationModelSerializationTest {
         VfModule vfModule = new VfModule(newModelInfo(), null, null, null,
             null, null, null, null, null, false,
             /* HERE ====> */ USE_PRELOAD,
-            null, null, null, null, null, null, null);
+            null, null, null, null, null, null, null, null);
 
         assertThat(vfModule, jsonPartEquals("sdncPreLoad", USE_PRELOAD));
         assertThat(vfModule, jsonNodeAbsent("usePreload"));
@@ -177,7 +182,7 @@ public class InstantiationModelSerializationTest {
             /* HERE ====> */ VOLUME_GROUP_INSTANCE_NAME,
             null, null, null, null, null, null,
             false, null, null, null, null, null,
-            null, null, null);
+            null, null, null, null);
 
         assertThat(vfModule, jsonPartEquals("volumeGroupName", VOLUME_GROUP_INSTANCE_NAME));
         assertThat(vfModule, jsonNodeAbsent("volumeGroupInstanceName"));
diff --git a/vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java b/vid-app-common/src/test/java/org/onap/vid/model/serviceInstantiation/VfModuleTest.java
new file mode 100644 (file)
index 0000000..a1c78c4
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2020 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.onap.vid.model.serviceInstantiation;
+
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
+import static org.hamcrest.core.AllOf.allOf;
+import static org.onap.vid.testUtils.TestUtils.setStringsInStringProperties;
+
+import org.onap.vid.mso.model.ModelInfo;
+import org.testng.annotations.Test;
+
+public class VfModuleTest {
+
+    @Test
+    public void cloneWithLcpCloudRegionIdAndTenantId() {
+        String targetLcpCloudRegionId = "dictated lcpCloudRegionId";
+        String targetTenantId = "dictated tenantId";
+
+        VfModule originVfModule = createVfModule();
+
+        assertThat(originVfModule.cloneWith(targetLcpCloudRegionId, targetTenantId), allOf(
+            hasProperty("lcpCloudRegionId", equalTo(targetLcpCloudRegionId)),
+            hasProperty("tenantId", equalTo(targetTenantId)),
+            jsonEquals(originVfModule).whenIgnoringPaths("lcpCloudRegionId", "tenantId")
+        ));
+
+        // verify vfModule did not mutate
+        assertThat(originVfModule, jsonEquals(createVfModule()));
+    }
+
+    private VfModule createVfModule() {
+        VfModule vfModule = new VfModule(
+            setStringsInStringProperties(new ModelInfo()),
+            null, null, null, null, null,
+            null, null, null, true, true,
+            null, null, true, null, true,
+            true, null, null);
+
+        return setStringsInStringProperties(vfModule);
+    }
+}
\ No newline at end of file
index 10456be..cfde52a 100644 (file)
@@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import io.joshworks.restclient.http.HttpResponse;
 import org.onap.vid.testUtils.TestUtils;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 public class MsoUtilTest {
@@ -67,4 +68,26 @@ public class MsoUtilTest {
         assertThat(result.getStatus()).isEqualTo(SC_OK);
     }
 
+    @DataProvider
+    public static Object[][] formatExceptionAdditionalInfo() {
+        return new Object[][]{
+            {"message", "Http Code:400, message"},
+
+            {null, "Http Code:400"},
+
+            {"{\"requestError\":{\"serviceException\":{\"messageId\":\"SVC0002\",\"text\":\"message\"}}}",
+                "Http Code:400, \"messageId\":\"SVC0002\",\"text\":\"message\""},
+
+            {"{\"validJson\": \"Error: message\"}", "Http Code:400, {\"validJson\": \"Error: message\"}"},
+
+            {"{\"serviceException\":{\"messageId\":\"SVC0002\",\"text\":\"Error: message\"}}",
+                "Http Code:400, \"messageId\":\"SVC0002\",\"text\":\"Error: message\""},
+        };
+    }
+
+    @Test(dataProvider = "formatExceptionAdditionalInfo")
+    public void formatExceptionAdditionalInfo_payloadWithError400_doNotReturnNull(String payload, String expected) {
+        assertThat(MsoUtil.formatExceptionAdditionalInfo(400, payload))
+            .isEqualTo(expected);
+    }
 }
diff --git a/vid-app-common/src/test/java/org/onap/vid/mso/model/RequestParametersVfModuleTest.java b/vid-app-common/src/test/java/org/onap/vid/mso/model/RequestParametersVfModuleTest.java
new file mode 100644 (file)
index 0000000..e339af0
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2020 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.onap.vid.mso.model;
+
+import static java.util.Collections.emptyList;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.testng.annotations.Test;
+
+public class RequestParametersVfModuleTest {
+
+    @Test
+    public void RequestParametersVfModuleOrVolumeGroupInstantiation_whenUsePreloadIsNull_thenLiteralFalseIsSerialized() {
+        Boolean usePreload = null;
+        assertThat(
+            new RequestParametersVfModuleOrVolumeGroupInstantiation(emptyList(), usePreload, ""),
+            jsonPartEquals("usePreload", false)
+        );
+    }
+
+    @Test
+    public void RequestParametersVfModuleUpgrade_whenUsePreloadIsNull_thenLiteralFalseIsSerialized() {
+        Boolean usePreload = null;
+        assertThat(
+            new RequestParametersVfModuleUpgrade(emptyList(), usePreload, "", false, false),
+            jsonPartEquals("usePreload", false)
+        );
+    }
+
+}
diff --git a/vid-app-common/src/test/java/org/onap/vid/properties/FeatureSetsManagerTest.kt b/vid-app-common/src/test/java/org/onap/vid/properties/FeatureSetsManagerTest.kt
new file mode 100644 (file)
index 0000000..9cf7aa6
--- /dev/null
@@ -0,0 +1,101 @@
+package org.onap.vid.properties
+
+import org.hamcrest.CoreMatchers.*
+import org.hamcrest.MatcherAssert.assertThat
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.InjectMocks
+import org.mockito.Mock
+import org.mockito.Mockito.*
+import org.onap.vid.testUtils.TestUtils
+import org.springframework.web.context.request.RequestContextHolder
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.Test
+import org.togglz.core.manager.FeatureManager
+import javax.servlet.ServletContext
+import javax.servlet.http.Cookie
+import javax.servlet.http.HttpServletRequest
+import org.hamcrest.CoreMatchers.`is` as _is
+import org.mockito.Mockito.`when` as _when
+
+class FeatureSetsManagerTest {
+    @Mock
+    lateinit var defaultFeatureManager: FeatureManager
+    @Mock
+    lateinit var servletContext: ServletContext
+    @Mock
+    lateinit var alternativeFeatureSetNameProvider: AlternativeFeatureSetNameProvider
+    @InjectMocks
+    lateinit var featureSetsManager: FeatureSetsManager
+
+    private val alternativeFeatureSetNameFromCookie = AlternativeFeatureSetNameFromCookie()
+
+    @BeforeMethod
+    fun setUp() {
+        TestUtils.initMockitoMocks(this)
+    }
+
+    @Test
+    fun `isActive - without alternative features set name - delegates to default and no file loaded`() {
+        _when(defaultFeatureManager.isActive(Features.FLAG_1810_AAI_LOCAL_CACHE)).thenReturn(true)
+        _when(alternativeFeatureSetNameProvider.alternativeFeatureSetName).thenReturn(null)
+
+        assertThat(featureSetsManager.isActive(Features.FLAG_1810_AAI_LOCAL_CACHE), _is(true))
+
+        verifyZeroInteractions(servletContext) // implies no other file loaded
+        verify(defaultFeatureManager, times(1)).isActive(Features.FLAG_1810_AAI_LOCAL_CACHE)
+    }
+
+    @Test
+    fun `isActive - with alternative features set - brings flags from alternative`() {
+        _when(servletContext.getRealPath(anyString())).thenReturn(this.javaClass.getResource("/").path)
+        _when(alternativeFeatureSetNameProvider.alternativeFeatureSetName).thenReturn("example.features.properties")
+
+        assertThat(featureSetsManager.isActive(Features.FLAG_1810_AAI_LOCAL_CACHE), _is(true))
+        assertThat(featureSetsManager.isActive(Features.FLAG_1902_NEW_VIEW_EDIT), _is(false))
+        verifyZeroInteractions(defaultFeatureManager)
+    }
+
+    @Test
+    fun `isActive - with non-existing alternative features set - fallback is to all flags off`() {
+        _when(servletContext.getRealPath(anyString())).thenReturn(this.javaClass.getResource("/").path)
+        _when(alternativeFeatureSetNameProvider.alternativeFeatureSetName).thenReturn("non-existing")
+
+        assertThat(featureSetsManager, not(nullValue()))
+        assertThat(
+                featureSetsManager.features.map { featureSetsManager.isActive(it) },
+                not(hasItem(true))
+        )
+    }
+
+    @Test
+    fun `valueFromCookie - given no request - return null`() {
+        assertThat(alternativeFeatureSetNameFromCookie.valueFromCookie(null), _is(nullValue()))
+    }
+
+    @Test
+    fun `valueFromCookie - given request - return the correct cookie value`() {
+        val servletRequestMock = mock(HttpServletRequest::class.java)
+        _when(servletRequestMock.cookies).thenReturn(arrayOf(Cookie("features.set", "value")))
+
+        assertThat(alternativeFeatureSetNameFromCookie.valueFromCookie(servletRequestMock), _is("value"))
+    }
+
+    @Test
+    fun `valueFromCookie - given request without cookies - return null`() {
+        val servletRequestMock = mock(HttpServletRequest::class.java)
+        _when(servletRequestMock.cookies).thenReturn(emptyArray())
+
+        assertThat(alternativeFeatureSetNameFromCookie.valueFromCookie(servletRequestMock), _is(nullValue()))
+    }
+
+    @Test
+    fun `currentHttpRequest - when no current request - return null`() {
+        assertPrecondition()
+        assertThat(alternativeFeatureSetNameFromCookie.currentHttpRequest(), _is(nullValue()))
+    }
+
+    private fun assertPrecondition() {
+        assertThat("precondition for test not met: static RequestContextHolder.getRequestAttributes should be null",
+                RequestContextHolder.getRequestAttributes(), _is(nullValue()))
+    }
+}
index 363c6ff..6826b1e 100644 (file)
@@ -33,7 +33,8 @@ public class AlwaysValidRoleValidatorTest {
 
     @Test
     public void testIsServicePermitted() {
-        assertTrue(new AlwaysValidRoleValidator().isServicePermitted("any", "any"));
+        WithPermissionProperties emptyPermissionProperties = new WithPermissionProperties() {};
+        assertTrue(new AlwaysValidRoleValidator().isServicePermitted(emptyPermissionProperties));
     }
 
     @Test
index c1033d2..8d81c92 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.vid.roles;
 
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
 
@@ -42,7 +43,7 @@ import org.testng.annotations.Test;
 public class RoleProviderTest {
 
     private static final String SAMPLE_SUBSCRIBER = "sampleSubscriber";
-    private static final String SAMPLE_CUSTOMER_ID = "sampleCustomerId";
+    private static final String SAMPLE_SUBSCRIBER_ID = "subscriberId";
     private static final String SERVICE_TYPE_LOGS = "LOGS";
     private static final String TENANT_PERMITTED = "PERMITTED";
     private static final String SAMPLE_SERVICE = "sampleService";
@@ -58,13 +59,16 @@ public class RoleProviderTest {
     @Mock
     private AaiResponse<SubscriberList> subscriberListResponse;
 
+    @Mock
+    private RoleValidatorFactory roleValidatorFactory;
+
     private RoleProvider roleProvider;
 
 
     @BeforeMethod
     public void setUp() {
         initMocks(this);
-        roleProvider = new RoleProvider(aaiService, httpServletRequest -> 5, httpServletRequest -> createRoles());
+        roleProvider = new RoleProvider(aaiService, roleValidatorFactory, httpServletRequest -> 5, httpServletRequest -> createRoles());
     }
 
     @Test
@@ -83,7 +87,7 @@ public class RoleProviderTest {
         Role role = roleProvider.createRoleFromStringArr(roleParts, SAMPLE_ROLE_PREFIX);
 
         assertThat(role.getEcompRole()).isEqualTo(EcompRole.READ);
-        assertThat(role.getSubscribeName()).isEqualTo(SAMPLE_CUSTOMER_ID);
+        assertThat(role.getSubscriberId()).isEqualTo(SAMPLE_SUBSCRIBER_ID);
         assertThat(role.getTenant()).isEqualTo(SAMPLE_TENANT);
         assertThat(role.getServiceType()).isEqualTo(SAMPLE_SERVICE);
     }
@@ -97,7 +101,7 @@ public class RoleProviderTest {
         Role role = roleProvider.createRoleFromStringArr(roleParts, SAMPLE_ROLE_PREFIX);
 
         assertThat(role.getEcompRole()).isEqualTo(EcompRole.READ);
-        assertThat(role.getSubscribeName()).isEqualTo(SAMPLE_CUSTOMER_ID);
+        assertThat(role.getSubscriberId()).isEqualTo(SAMPLE_SUBSCRIBER_ID);
         assertThat(role.getServiceType()).isEqualTo(SAMPLE_SERVICE);
         assertThat(role.getTenant()).isNullOrEmpty();
     }
@@ -111,7 +115,7 @@ public class RoleProviderTest {
 
     @Test
     public void shouldProperlyRetrieveUserRolesWhenPermissionIsDifferentThanRead() {
-        Role expectedRole = new Role(EcompRole.READ, SAMPLE_CUSTOMER_ID, SAMPLE_SERVICE, SAMPLE_TENANT);
+        Role expectedRole = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER_ID, SAMPLE_SERVICE, SAMPLE_TENANT, owningEntityId());
         setSubscribers();
 
         List<Role> userRoles = roleProvider.getUserRoles(request);
@@ -121,7 +125,7 @@ public class RoleProviderTest {
         Role actualRole = userRoles.get(0);
 
         assertThat(actualRole.getTenant()).isEqualTo(expectedRole.getTenant());
-        assertThat(actualRole.getSubscribeName()).isEqualTo(expectedRole.getSubscribeName());
+        assertThat(actualRole.getSubscriberId()).isEqualTo(expectedRole.getSubscriberId());
         assertThat(actualRole.getServiceType()).isEqualTo(expectedRole.getServiceType());
     }
 
@@ -132,21 +136,38 @@ public class RoleProviderTest {
 
     @Test
     public void shouldReturnNotReadOnlyPermissionWhenRolesArePresent() {
-        assertThat(roleProvider.userPermissionIsReadOnly(Lists.list(new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE, SAMPLE_TENANT)))).isFalse();
+        assertThat(roleProvider.userPermissionIsReadOnly(Lists.list(new Role(
+            EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE, SAMPLE_TENANT, owningEntityId())))).isFalse();
     }
 
     @Test
     public void userShouldHavePermissionToReadLogsWhenServiceAndTenantAreCorrect() {
-        Role withoutPermission = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE, SAMPLE_TENANT);
-        Role withPermission = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SERVICE_TYPE_LOGS, TENANT_PERMITTED);
+        Role withoutPermission = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE, SAMPLE_TENANT, owningEntityId());
+        Role withPermission = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SERVICE_TYPE_LOGS, TENANT_PERMITTED, owningEntityId());
 
         assertThat(roleProvider.userPermissionIsReadLogs(Lists.list(withoutPermission, withPermission))).isTrue();
     }
 
+    @Test
+    public void getUserRolesValidator_shouldReturnValidatorFromFactory() {
+        RoleValidator expectedRoleValidator = new AlwaysValidRoleValidator();
+        when(roleValidatorFactory.by(any())).thenReturn(expectedRoleValidator);
+
+        RoleValidator result = roleProvider.getUserRolesValidator(request);
+
+        assertThat(result).isEqualTo(expectedRoleValidator);
+    }
+
+    private String owningEntityId() {
+        // while translateOwningEntityNameToOwningEntityId does nothing, no translation happens.
+        // this will be changed later.
+        return SAMPLE_SUBSCRIBER;
+    }
+
     private void setSubscribers() {
         Subscriber subscriber = new Subscriber();
         subscriber.subscriberName = SAMPLE_SUBSCRIBER;
-        subscriber.globalCustomerId = SAMPLE_CUSTOMER_ID;
+        subscriber.globalCustomerId = SAMPLE_SUBSCRIBER_ID;
         SubscriberList subscriberList = new SubscriberList(Lists.list(subscriber));
         when(aaiService.getFullSubscriberList()).thenReturn(subscriberListResponse);
         when(subscriberListResponse.getT()).thenReturn(subscriberList);
diff --git a/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByOwningEntityTest.java b/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByOwningEntityTest.java
new file mode 100644 (file)
index 0000000..d84ac6e
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 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.onap.vid.roles;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+import static org.testng.Assert.assertFalse;
+
+import com.google.common.collect.ImmutableList;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class RoleValidatorByOwningEntityTest {
+
+    private static final String OWNING_ENTITY_ID = "owningEntityId";
+    private static final String SUBSCRIBER_NAME = "subscriber_name";
+    private static final String NOT_MATCHING_OWNING_ENTITY_ID = "notMatchingOwningEntityId";
+
+    private static final String SERVICE_TYPE = "serviceType";
+    private static final String GLOBAL_CUSTOMER_ID = "globalCustomerId";
+    private static final String TENANT_NAME = "tenantName";
+
+
+    private RoleValidatorByOwningEntity roleValidatorByOwningEntity;
+
+    @BeforeMethod
+    public void setup() {
+        final Role SAMPLE_ROLE = new Role(EcompRole.READ, "", "", "", OWNING_ENTITY_ID);
+        roleValidatorByOwningEntity = new RoleValidatorByOwningEntity(ImmutableList.of(SAMPLE_ROLE));
+    }
+
+    @Test
+    public void testIsSubscriberPermitted() {
+        assertFalse(roleValidatorByOwningEntity.isSubscriberPermitted(SUBSCRIBER_NAME));
+    }
+
+    @Test
+    public void isServicePermitted_owningEntityMatch_returnTrue() {
+        PermissionPropertiesOwningEntity permittedOwningEntity =
+            new PermissionPropertiesOwningEntity(OWNING_ENTITY_ID);
+
+        assertThat(roleValidatorByOwningEntity.isServicePermitted(permittedOwningEntity), is(true));
+    }
+
+    @DataProvider
+    public static Object[][] nonMatchingPermissionProperties() {
+        return new Object[][]{
+            {new PermissionPropertiesOwningEntity(NOT_MATCHING_OWNING_ENTITY_ID)},
+            {new PermissionPropertiesOwningEntity("")},
+            {new WithPermissionProperties() {}},
+            {mock(PermissionPropertiesOwningEntity.class,
+                withSettings().name("PermissionPropertiesOwningEntity with null owningEntityId"))},
+            {new PermissionPropertiesSubscriberAndServiceType(OWNING_ENTITY_ID, OWNING_ENTITY_ID)},
+        };
+    }
+
+    @Test(dataProvider = "nonMatchingPermissionProperties")
+    public void isServicePermitted_nonMatchingPermissionProperties_returnFalse(WithPermissionProperties permissionProperties) {
+        assertThat(permissionProperties.toString(), roleValidatorByOwningEntity.isServicePermitted(
+            permissionProperties
+        ), is(false));
+    }
+
+    @Test
+    public void testIsTenantPermitted() {
+        assertFalse(roleValidatorByOwningEntity.isTenantPermitted(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, TENANT_NAME));
+    }
+
+}
diff --git a/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByRolesTest.java b/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorByRolesTest.java
deleted file mode 100644 (file)
index 9362ec9..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * VID
- * ================================================================================
- * Copyright (C) 2017 - 2019 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.onap.vid.roles;
-
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import java.util.List;
-import java.util.Map;
-import org.onap.vid.mso.rest.RequestDetails;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class RoleValidatorByRolesTest {
-
-    private static final String SAMPLE_SUBSCRIBER = "sampleSubscriber";
-    private static final String NOT_MATCHING_SUBSCRIBER = "notMatchingSubscriber";
-    private static final String SAMPLE_SERVICE_TYPE = "sampleServiceType";
-    private static final String NOT_MATCHING_TENANT = "notMatchingTenant";
-    private static final String SAMPLE_TENANT = "sampleTenant";
-
-    private static final Role SAMPLE_ROLE = new Role(EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SAMPLE_TENANT);
-
-    private List<Role> roles = ImmutableList.of(SAMPLE_ROLE);
-    private Map<String, Object> subscriberInfo = ImmutableMap.of("globalSubscriberId", SAMPLE_SUBSCRIBER);
-    private Map<String, Object> requestParameters = ImmutableMap.of("subscriptionServiceType", SAMPLE_SERVICE_TYPE);
-    private Map<String, Object> requestDetailsProperties = ImmutableMap.of("subscriberInfo", subscriberInfo, "requestParameters", requestParameters);
-    private RequestDetails requestDetails;
-    private RoleValidatorByRoles roleValidator;
-
-    @BeforeMethod
-    public void setUp() {
-        roleValidator = new RoleValidatorByRoles(roles);
-        requestDetails = new RequestDetails();
-    }
-
-    @Test
-    public void shouldPermitSubscriberWhenNameMatchesAndRolesAreEnabled() {
-        assertThat(roleValidator.isSubscriberPermitted(SAMPLE_SUBSCRIBER)).isTrue();
-    }
-
-    @Test
-    public void shouldNotPermitSubscriberWhenNameNotMatches() {
-        assertThat(roleValidator.isSubscriberPermitted(NOT_MATCHING_SUBSCRIBER)).isFalse();
-    }
-
-    @Test
-    public void shouldPermitServiceWhenNamesMatches() {
-        assertThat(roleValidator.isServicePermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE)).isTrue();
-    }
-
-
-    @Test
-    public void shouldNotPermitServiceWhenSubscriberNameNotMatches() {
-        assertThat(roleValidator.isServicePermitted(NOT_MATCHING_SUBSCRIBER, SAMPLE_SERVICE_TYPE)).isFalse();
-    }
-
-    @Test
-    public void shouldNotPermitServiceWhenServiceTypeNotMatches() {
-        assertThat(roleValidator.isServicePermitted(SAMPLE_SUBSCRIBER, NOT_MATCHING_SUBSCRIBER)).isFalse();
-    }
-
-    @Test
-    public void shouldPermitTenantWhenNameMatches() {
-        assertThat(roleValidator.isTenantPermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SAMPLE_TENANT)).isTrue();
-    }
-
-
-    @Test
-    public void shouldNotPermitTenantWhenNameNotMatches() {
-        assertThat(roleValidator.isTenantPermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, NOT_MATCHING_TENANT)).isFalse();
-    }
-
-    @Test
-    public void shouldValidateProperlySORequest() {
-        requestDetails.setAdditionalProperty("requestDetails", requestDetailsProperties);
-
-        assertThat(roleValidator.isMsoRequestValid(requestDetails)).isTrue();
-    }
-
-    @Test
-    public void shouldValidateUnknownSORequest() {
-        assertThat(roleValidator.isMsoRequestValid(new RequestDetails())).isTrue();
-    }
-
-    @Test
-    public void shouldRejectSORequestWhenSubscriberNotMatches() {
-        Map<String, Object> subscriberInfo = ImmutableMap.of("globalSubscriberId", "sample");
-        Map<String, Object> requestDetailsProperties = ImmutableMap.of("subscriberInfo", subscriberInfo, "requestParameters", requestParameters);
-        requestDetails.setAdditionalProperty("requestDetails", requestDetailsProperties);
-
-        assertThat(roleValidator.isMsoRequestValid(requestDetails)).isFalse();
-    }
-}
diff --git a/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorBySubscriberAndServiceTypeTest.java b/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorBySubscriberAndServiceTypeTest.java
new file mode 100644 (file)
index 0000000..b6958cd
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 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.onap.vid.roles;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class RoleValidatorBySubscriberAndServiceTypeTest {
+
+    private static final String SAMPLE_SUBSCRIBER = "sampleSubscriber";
+    private static final String NOT_MATCHING_SUBSCRIBER = "notMatchingSubscriber";
+    private static final String SAMPLE_SERVICE_TYPE = "sampleServiceType";
+    private static final String NOT_MATCHING_TENANT = "notMatchingTenant";
+    private static final String SAMPLE_TENANT = "sampleTenant";
+    private static final String SOME_OWNING_ENTITY_ID = "someOwningEntityId";
+
+    private static final Role SAMPLE_ROLE = new Role(
+        EcompRole.READ, SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SAMPLE_TENANT, SOME_OWNING_ENTITY_ID);
+
+    private List<Role> roles = ImmutableList.of(SAMPLE_ROLE);
+    private RoleValidatorBySubscriberAndServiceType roleValidatorBySubscriberAndServiceType;
+
+    @BeforeMethod
+    public void setUp() {
+        roleValidatorBySubscriberAndServiceType = new RoleValidatorBySubscriberAndServiceType(roles);
+    }
+
+    @Test
+    public void shouldPermitSubscriberWhenNameMatchesAndRolesAreEnabled() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isSubscriberPermitted(SAMPLE_SUBSCRIBER)).isTrue();
+    }
+
+    @Test
+    public void shouldNotPermitSubscriberWhenNameNotMatches() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isSubscriberPermitted(NOT_MATCHING_SUBSCRIBER)).isFalse();
+    }
+
+    @Test
+    public void shouldPermitServiceWhenNamesMatches() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isServicePermitted(
+            new PermissionPropertiesSubscriberAndServiceType(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE))).isTrue();
+    }
+
+    @Test
+    public void isServicePermitted_serviceWithAllPermissionProperties_isPermitted() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isServicePermitted(
+            new AllPermissionProperties(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SOME_OWNING_ENTITY_ID))).isTrue();
+    }
+
+    @Test
+    public void shouldNotPermitServiceWhenSubscriberNameNotMatches() {
+        assertThat(
+            roleValidatorBySubscriberAndServiceType.isServicePermitted(
+                new PermissionPropertiesSubscriberAndServiceType(NOT_MATCHING_SUBSCRIBER, SAMPLE_SERVICE_TYPE))).isFalse();
+    }
+
+    @Test
+    public void shouldNotPermitServiceWhenServiceTypeNotMatches() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isServicePermitted(
+            new PermissionPropertiesSubscriberAndServiceType(SAMPLE_SUBSCRIBER, NOT_MATCHING_SUBSCRIBER))).isFalse();
+    }
+
+    @Test
+    public void isServicePermitted_owningEntityPermissionProperties_isNotPermitted() {
+        assertThat(roleValidatorBySubscriberAndServiceType.isServicePermitted(
+            new PermissionPropertiesOwningEntity(SAMPLE_SUBSCRIBER))).isFalse();
+    }
+
+    @Test
+    public void shouldPermitTenantWhenNameMatches() {
+        assertThat(roleValidatorBySubscriberAndServiceType
+            .isTenantPermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SAMPLE_TENANT)).isTrue();
+    }
+
+    @Test
+    public void shouldPermitTenantWhenNameMatchesCaseInsensitive() {
+        assertThat(roleValidatorBySubscriberAndServiceType
+            .isTenantPermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, SAMPLE_TENANT.toUpperCase())).isTrue();
+    }
+
+
+    @Test
+    public void shouldNotPermitTenantWhenNameNotMatches() {
+        assertThat(roleValidatorBySubscriberAndServiceType
+            .isTenantPermitted(SAMPLE_SUBSCRIBER, SAMPLE_SERVICE_TYPE, NOT_MATCHING_TENANT)).isFalse();
+    }
+
+}
diff --git a/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorFactoryTest.java b/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorFactoryTest.java
new file mode 100644 (file)
index 0000000..b3c71c5
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2020 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.onap.vid.roles;
+
+import static java.util.Collections.emptyList;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.List;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.vid.properties.Features;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.togglz.core.manager.FeatureManager;
+
+public class RoleValidatorFactoryTest {
+
+    @InjectMocks
+    private RoleValidatorFactory roleValidatorFactory;
+
+    @Mock
+    private FeatureManager featureManager;
+
+    @BeforeClass
+    public void initMocks() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @AfterMethod
+    public void reset() {
+        Mockito.reset(featureManager);
+    }
+
+    @Test (dataProvider = "presetRoleValidatorClass")
+    public void returnRoleValidatorByGivenClass_And_RoleManagementActivated_And_FeatureFlag(Class expectedClass,boolean isDisabledRoles, boolean flagActive ) {
+
+        when(featureManager.isActive(Features.FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY)).thenReturn(flagActive);
+        RoleValidator roleValidator = roleValidatorFactory.by(emptyList(), isDisabledRoles);
+        assertThat(roleValidator, instanceOf(expectedClass));
+    }
+
+    @DataProvider
+    public static Object[][] presetRoleValidatorClass() {
+        return new Object[][] {
+            {RoleValidatorsComposer.class, false, true},
+            {AlwaysValidRoleValidator.class, true, true},
+            {RoleValidatorBySubscriberAndServiceType.class, false, false},
+            {AlwaysValidRoleValidator.class, true, false}
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorsComposerTest.java b/vid-app-common/src/test/java/org/onap/vid/roles/RoleValidatorsComposerTest.java
new file mode 100644 (file)
index 0000000..c0892da
--- /dev/null
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * VID
+ * ================================================================================
+ * Copyright (C) 2017 - 2020 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.onap.vid.roles;
+
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.withSettings;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class RoleValidatorsComposerTest {
+
+    private RoleValidator alwaysTrueRoles;
+    private RoleValidator alwaysFalseRoles;
+
+    @DataProvider
+    public static Object[][] allInterfaceFunctions() {
+        return Stream.<Function<RoleValidator, Boolean>>of(
+            (RoleValidator o) -> o.isSubscriberPermitted("subscriberId"),
+            (RoleValidator o) -> o.isServicePermitted(new WithPermissionProperties() {}),
+            (RoleValidator o) -> o.isTenantPermitted("subscriberId", "serviceType", "tenantName")
+        ).map(it -> new Object[]{it}).collect(toList()).toArray(new Object[][]{});
+    }
+
+    @BeforeMethod
+    public void setUp() {
+        alwaysTrueRoles = mock(RoleValidator.class, withSettings().defaultAnswer(o -> true));
+        alwaysFalseRoles = mock(RoleValidator.class);
+    }
+
+    @Test(dataProvider = "allInterfaceFunctions")
+    public void emptyComposite_returnsFalse(Function<RoleValidator, Boolean> interfaceFunction) {
+        RoleValidatorsComposer underTest = new RoleValidatorsComposer();
+
+        assertThat(
+            interfaceFunction.apply(underTest),
+            is(false)
+        );
+
+    }
+
+    @Test(dataProvider = "allInterfaceFunctions")
+    public void falseAndTrueComposite_returnsTrue(Function<RoleValidator, Boolean> interfaceFunction) {
+        RoleValidatorsComposer underTest =
+            new RoleValidatorsComposer(alwaysFalseRoles, alwaysFalseRoles, alwaysTrueRoles);
+
+        assertThat(
+            interfaceFunction.apply(underTest),
+            is(true)
+        );
+    }
+
+    @Test(dataProvider = "allInterfaceFunctions")
+    public void trueAndFalseComposite_returnsTrueAndShortCircuits(Function<RoleValidator, Boolean> interfaceFunction) {
+        RoleValidatorsComposer underTest = new RoleValidatorsComposer(alwaysTrueRoles, alwaysFalseRoles);
+
+        assertThat(
+            interfaceFunction.apply(underTest),
+            is(true)
+        );
+
+        verifyZeroInteractions(alwaysFalseRoles);
+    }
+
+    @Test(dataProvider = "allInterfaceFunctions")
+    public void falseAndFalseComposite_returnsFalse(Function<RoleValidator, Boolean> interfaceFunction) {
+        RoleValidatorsComposer underTest = new RoleValidatorsComposer(alwaysFalseRoles, alwaysFalseRoles);
+        
+        assertThat(
+            interfaceFunction.apply(underTest),
+            is(false)
+        );
+    }
+
+    @Test
+    public void secondaryConstructor_givenSetIfValidators_returnsTrue() {
+        RoleValidatorsComposer underTest = new RoleValidatorsComposer(
+            ImmutableSet.of(alwaysTrueRoles)
+        );
+
+        assertThat(underTest.isSubscriberPermitted("anything"), is(true));
+    }
+
+}
index 2904183..67d3d4a 100644 (file)
@@ -50,7 +50,10 @@ import java.util.Optional;
 import java.util.concurrent.ConcurrentSkipListSet;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
 import org.jetbrains.annotations.NotNull;
 import org.mockito.Mock;
 import org.mockito.stubbing.Answer;
@@ -79,6 +82,7 @@ public class AAITreeNodeBuilderTest {
 
     private ExecutorService executorService;
     private Logging logging = new Logging();
+    private static final Logger logger = LogManager.getLogger(AAITreeNodeBuilderTest.class);
 
     private static final ObjectMapper mapper = new ObjectMapper();
 
@@ -92,7 +96,9 @@ public class AAITreeNodeBuilderTest {
     private void buildNodeAndAssert(JsonNode inputNode, AAITreeNode expectedNode, NodeType nodeType){
         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
         when(aaiClientMock.typedAaiRest(Unchecked.toURI("anyUrl"), JsonNode.class, null, HttpMethod.GET, false)).thenReturn(inputNode);
-        AAITreeNode actualNode = aaiTreeNodeBuilder.buildNode(
+        AAITreeNode actualNode;
+        try {
+            actualNode = aaiTreeNodeBuilder.buildNode(
                 nodeType,
                 "anyUrl",
                 null,
@@ -100,7 +106,16 @@ public class AAITreeNodeBuilderTest {
                 nodesAccumulator,
                 executorService,
                 AAI_TREE_PATHS.getSubTree(new AAIServiceTree.AaiRelationship(nodeType))
-        ).get(0);
+            ).get(0);
+        } catch (Throwable e) {
+            //print stack traces for more information in case of failure
+            System.out.println("Failed to build node by aaiTreeNodeBuilder");
+            ExceptionUtils.getThrowableList(e)
+                .stream()
+                .peek(it ->System.err.println(it.getLocalizedMessage()))
+                .forEach(Throwable::printStackTrace);
+            throw e;
+        }
         assertThat(actualNode, jsonEquals(expectedNode).when(IGNORING_ARRAY_ORDER, IGNORING_EXTRA_FIELDS).whenIgnoringPaths("relationshipList","children[0].relationshipList"));
     }
 
index d3b2a48..a374826 100644 (file)
@@ -183,7 +183,7 @@ public class AaiServiceImplTest {
         AaiResponse<Services> aaiResponseServices = new AaiResponse<>(services, null, HttpStatus.SC_OK);
 
         when(aaiClient.getSubscriberData(SUBSCRIBER_ID, false)).thenReturn(aaiResponseServices);
-        when(roleValidator.isServicePermitted(eq(GLOBAL_CUSTOMER_ID), anyString())).thenReturn(Boolean.TRUE);
+        when(roleValidator.isServicePermitted(any())).thenReturn(Boolean.TRUE);
 
         AaiResponse actualResponse = aaiService.getSubscriberData(SUBSCRIBER_ID, roleValidator, false);
         List<ServiceSubscription> actualServiceSubscriptions = ((AaiResponse<Services>) actualResponse)
index 6aa6705..4d6566f 100644 (file)
 
 package org.onap.vid.services;
 
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.arrayWithSize;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import org.jetbrains.annotations.NotNull;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.onap.vid.aai.AaiClientInterface;
 import org.onap.vid.aai.AaiResponse;
+import org.onap.vid.aai.ServiceInstance;
 import org.onap.vid.aai.model.AaiGetPnfResponse;
 import org.onap.vid.aai.model.AaiGetPnfs.Pnf;
 import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
 import org.onap.vid.aai.model.LogicalLinkResponse;
+import org.onap.vid.aai.model.OwningEntityResponse;
+import org.onap.vid.aai.model.ProjectResponse;
 import org.onap.vid.aai.model.Relationship;
 import org.onap.vid.aai.model.RelationshipData;
 import org.onap.vid.aai.model.RelationshipList;
 import org.onap.vid.aai.model.ServiceRelationships;
+import org.onap.vid.model.ServiceInstanceSearchResult;
 import org.onap.vid.model.aaiTree.AAITreeNode;
-import org.onap.vid.roles.Role;
 import org.onap.vid.roles.RoleValidator;
+import org.onap.vid.roles.RoleValidatorFactory;
+import org.onap.vid.roles.WithPermissionProperties;
+import org.onap.vid.testUtils.TestUtils;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -61,6 +79,9 @@ public class AaiServiceTest {
     @Mock
     private AaiClientInterface aaiClientInterface;
 
+    @Mock
+    private RoleValidatorFactory roleValidatorFactory;
+
     @BeforeMethod
     public void initMocks(){
         MockitoAnnotations.initMocks(this);
@@ -68,7 +89,7 @@ public class AaiServiceTest {
 
     @Test
     public void testGetSpecificPnf(){
-        Pnf pnf = new Pnf("11111", null, null, null, null, null, null);
+        Pnf pnf = Pnf.builder().withPnfId("11111").build();
         AaiResponse<Pnf> aaiResponse = new AaiResponse<>(pnf, "aaaa", 200);
         Mockito.doReturn(aaiResponse).when(aaiClientInterface).getSpecificPnf(Mockito.anyString());
         AaiResponse<Pnf> specificPnf = aaiService.getSpecificPnf("1345667");
@@ -150,8 +171,6 @@ public class AaiServiceTest {
     public static Object[][] getTenantsData() {
         return new Object[][] {
                 {"customer1", "serviceType1", "tenant1", "customer1", "serviceType1", "tenant1", "id-1", true},
-                {"customer1", "serviceType1", "TeNant1", "customer1", "serviceType1", "tenant1", "id-1", true},
-                {"customer1", "serviceType1", "TENANT1", "customer1", "serviceType1", "tenant1", "id-1", true},
                 {"customer1", "serviceType1", "tenant2", "customer1", "serviceType1", "tenant1", "tenant2", false},
                 {"customer1", "serviceType1", null, "customer1", "serviceType1", "tenant1", "tenant2", true},
                 {"customer2", "serviceType1", "tenant1", "customer1", "serviceType1", "tenant1", "id-1", false},
@@ -162,14 +181,20 @@ public class AaiServiceTest {
     }
 
     @Test(dataProvider = "getTenantsData")
-    public void testGetTenants(String userGlobalCustomerId, String userServiceType, String userTenantName, String serviceGlobalCustomerId,
-                               String serviceServiceType, String serviceTenantName, String serviceTenantId, boolean expectedIsPermitted) {
+    public void testGetTenants(String userGlobalCustomerId, String userServiceType, String userTenantName,
+                                String serviceGlobalCustomerId, String serviceServiceType, String serviceTenantName,
+                                String serviceTenantId, boolean expectedIsPermitted) {
         GetTenantsResponse[] getTenantsResponses = new GetTenantsResponse[] {new GetTenantsResponse(null, null, serviceTenantName, serviceTenantId, false)};
         AaiResponse<GetTenantsResponse[]> aaiResponse = new AaiResponse<>(getTenantsResponses, null, 200);
         Mockito.doReturn(aaiResponse).when(aaiClientInterface).getTenants(serviceGlobalCustomerId, serviceServiceType);
-        Role role = new Role(null, userGlobalCustomerId, userServiceType, userTenantName);
-        RoleValidator roleValidator = RoleValidator.by(Collections.singletonList(role), false);
-        AaiResponse<GetTenantsResponse[]> actualTenants = aaiService.getTenants(serviceGlobalCustomerId, serviceServiceType, roleValidator);
+
+        RoleValidator roleValidatorMock = mock(RoleValidator.class);
+        when(roleValidatorMock.isTenantPermitted(
+            eq(userGlobalCustomerId), eq(userServiceType),
+            (userTenantName == null) ? anyString() : eq(userTenantName))
+        ).thenReturn(true);
+
+        AaiResponse<GetTenantsResponse[]> actualTenants = aaiService.getTenants(serviceGlobalCustomerId, serviceServiceType, roleValidatorMock);
 
         assertThat(actualTenants.getT(), arrayWithSize(1));
         assertThat(actualTenants.getT()[0].tenantName, equalTo(serviceTenantName));
@@ -206,4 +231,112 @@ public class AaiServiceTest {
         assertThat(anyMatch, equalTo(expectedMatch));
     }
 
+    @DataProvider
+    public static Object[][] dataToDestroy() {
+        return new Object[][]{
+            {"nothing"}, {"relationship-list"}, {"relationship"}, {"relationship-data"} ,{"owning-entity-id"}
+        };
+    }
+
+
+    @Test(dataProvider = "dataToDestroy")
+    public void relatedOwningEntityId_givenInstanceAndOptionalError_extractCorrectlyOrReturnNull(String dataToDestroy) throws JsonProcessingException {
+        ServiceInstance serviceInstance = new ObjectMapper().readValue((""
+            + "{ "
+            + "  \"service-instance-id\": \"5d521981-33be-4bb5-bb20-5616a9c52a5a\", "
+            + "  \"service-instance-name\": \"dfgh\", "
+            + "  \"service-type\": \"\", "
+            + "  \"service-role\": \"\", "
+            + "  \"environment-context\": \"null\", "
+            + "  \"workload-context\": \"null\", "
+            + "  \"model-invariant-id\": \"331a194d-9248-4533-88bc-62c812ccb5c1\", "
+            + "  \"model-version-id\": \"171b3887-e73e-479d-8ef8-2690bf74f2aa\", "
+            + "  \"resource-version\": \"1508832105498\", "
+            + "  \"orchestration-status\": \"Active\", "
+            + "  \"relationship-list\": { "
+            + "    \"relationship\": [ "
+            + "      { "
+            + "        \"related-to\": \"project\", "
+            + "        \"related-link\": \"/aai/v11/business/projects/project/Kennedy\", "
+            + "        \"relationship-data\": [ "
+            + "          { "
+            + "            \"relationship-key\": \"project.project-name\", "
+            + "            \"relationship-value\": \"Kennedy\" "
+            + "          } "
+            + "        ] "
+            + "      }, "
+            + "      { "
+            + "        \"related-to\": \"owning-entity\", "
+            + "        \"related-link\": \"/aai/v11/business/owning-entities/owning-entity/4d4ecf59-41f1-40d4-818d-885234680a42\", "
+            + "        \"relationship-data\": [ "
+            + "          { "
+            + "            \"relationship-key\": \"owning-entity.owning-entity-id\", "
+            + "            \"relationship-value\": \"4d4ecf59-41f1-40d4-818d-885234680a42\" "
+            + "          } "
+            + "        ] "
+            + "      } "
+            + "    ] "
+            + "  } "
+            + "}").replace(dataToDestroy, "omitted"), ServiceInstance.class);
+
+        if (dataToDestroy.equals("nothing")) {
+            assertThat(aaiService.relatedOwningEntityId(serviceInstance), is("4d4ecf59-41f1-40d4-818d-885234680a42"));
+        } else {
+            assertThat(aaiService.relatedOwningEntityId(serviceInstance), is(nullValue()));
+        }
+    }
+
+    @Test
+    public void testGetServicesByOwningEntityId() {
+
+        //given
+        List<String>  owningEntityIds = ImmutableList.of("43b8a85a-0421-4265-9069-117dd6526b8a", "26dcc4aa-725a-447d-8346-aa26dfaa4eb7");
+        OwningEntityResponse owningEntityResponse = TestUtils.readJsonResourceFileAsObject("/responses/aai/listServicesByOwningEntity.json", OwningEntityResponse.class);
+        when(aaiClientInterface.getServicesByOwningEntityId(owningEntityIds)).thenReturn(new AaiResponse<>(owningEntityResponse, "", 200));
+        RoleValidator roleValidator = createAlwaysTrueRoleValidator();
+
+        //when
+        List<ServiceInstanceSearchResult> result = aaiService.getServicesByOwningEntityId(owningEntityIds, roleValidator);
+
+        //then
+        ServiceInstanceSearchResult expected1 = new ServiceInstanceSearchResult(
+            "af9d52f9-13b2-4657-a198-463677f82dc0", "256cddb4-3aa1-43cc-a08f-315bb50b275e", "MSO-dev-service-type", "xbghrftgr_shani", null, null, null, "43b8a85a-0421-4265-9069-117dd6526b8a", true);
+        ServiceInstanceSearchResult expected2 = new ServiceInstanceSearchResult(
+            "49769492-5def-4c89-8e73-b236f958fa40", "e02fd6f2-7fc2-434b-a92d-15abdb24b68d", "JUST-another-service-type", "fghghfhgf",  null, null, null, "43b8a85a-0421-4265-9069-117dd6526b8a", true);
+        ServiceInstanceSearchResult expected3 = new ServiceInstanceSearchResult(
+            "1d8fd482-2f53-4d62-a7bd-20e4bab14c45", "256cddb4-3aa1-43cc-a08f-315bb50b275e", "MSO-dev-service-type", "Bryant", null, null, null, "26dcc4aa-725a-447d-8346-aa26dfaa4eb7", true);
+
+        assertThat(result, jsonEquals(ImmutableList.of(expected1, expected2, expected3)).when(IGNORING_ARRAY_ORDER).whenIgnoringPaths("[*].subscriberName")); //ignore in array
+    }
+
+    @NotNull
+    private RoleValidator createAlwaysTrueRoleValidator() {
+        RoleValidator roleValidator  = mock(RoleValidator.class);
+        when(roleValidator.isServicePermitted(any(WithPermissionProperties.class))).thenReturn(true);
+        return roleValidator;
+    }
+
+    @Test
+    public void testGetServicesByProjectNames() {
+
+        //given
+        List<String>  projectNames = ImmutableList.of("x1", "y2");
+        ProjectResponse projectResponse = TestUtils.readJsonResourceFileAsObject("/responses/aai/listServicesByProject.json", ProjectResponse.class);
+        when(aaiClientInterface.getServicesByProjectNames(projectNames)).thenReturn(new AaiResponse<>(projectResponse, "", 200));
+        RoleValidator roleValidator = createAlwaysTrueRoleValidator();
+
+        //when
+        List<ServiceInstanceSearchResult> result = aaiService.getServicesByProjectNames(projectNames, roleValidator);
+
+        //then
+        ServiceInstanceSearchResult expected1 = new ServiceInstanceSearchResult(
+            "3f826016-3ac9-4928-9561-beee75fd91d5", "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "Emanuel", "Lital_SRIOV2_001", null, null, null, null, true);
+        ServiceInstanceSearchResult expected2 = new ServiceInstanceSearchResult(
+            "7e4f8130-5dee-47c4-8770-1abc5f5ded83", "3d15d7ea-4174-49b6-89ec-e569381f7231", "vMOG", "justAname",  null, null, null, null, true);
+        ServiceInstanceSearchResult expected3 = new ServiceInstanceSearchResult(
+            "ff2d9326-1ef5-4760-aba0-0eaf372ae675", "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "Yoda", "anotherName", null, null, null, null, true);
+
+        assertThat(result, jsonEquals(ImmutableList.of(expected1, expected2, expected3)).when(IGNORING_ARRAY_ORDER).whenIgnoringPaths("[*].subscriberName")); //ignore in array
+    }
+
 }
index b953500..f611317 100644 (file)
@@ -22,7 +22,6 @@ package org.onap.vid.services;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.emptyMap;
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -65,6 +64,7 @@ import org.onap.vid.model.serviceInstantiation.VfModule;
 import org.onap.vid.model.serviceInstantiation.Vnf;
 import org.onap.vid.mso.RestObject;
 import org.onap.vid.mso.model.ModelInfo;
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue;
 import org.onap.vid.mso.rest.AsyncRequestStatus;
 import org.onap.vid.mso.rest.RequestStatus;
 import org.onap.vid.properties.Features;
@@ -237,7 +237,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
                 testApi,
                 instanceId,
                 action.name(),
-                UUID.randomUUID().toString(), null, null, null);
+                UUID.randomUUID().toString(), null, null, null, null);
     }
 
     private List<Map<String,String>> createInstanceParams() {
@@ -249,8 +249,10 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
         return instanceParams;
     }
 
-    protected VfModule createVfModule(String modelName, String modelVersionId, String modelCustomizationId,
-                                    List<Map<String, String>> instanceParams, Map<String, String> supplementaryParams, String instanceName, String volumeGroupInstanceName, boolean isAlacarte) {
+    protected VfModule createVfModule(
+        String modelName, String modelVersionId, String modelCustomizationId,
+        List<Map<String, String>> instanceParams, List<UserParamNameAndValue> supplementaryParams, String instanceName,
+        String volumeGroupInstanceName, boolean isAlacarte, Boolean usePreload) {
         ModelInfo vfModuleInfo = new ModelInfo();
         vfModuleInfo.setModelType("vfModule");
         vfModuleInfo.setModelName(modelName);
@@ -262,13 +264,14 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
             vfModuleInfo.setModelInvariantId("22222222-f63c-463e-ba94-286933b895f9");
             vfModuleInfo.setModelVersion("10.0");
             return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), "mdt1", null,
-                    "88a6ca3ee0394ade9403f075db23167e", instanceParams, supplementaryParams, false, true, null, UUID.randomUUID().toString(), null, null,
-                null, null, null);
+                "88a6ca3ee0394ade9403f075db23167e", instanceParams, supplementaryParams, false,
+                usePreload, null, UUID.randomUUID().toString(), null, null,
+                null, null, null, "originalName");
         }
 
         return new VfModule(vfModuleInfo, instanceName, volumeGroupInstanceName, Action.Create.name(), null, null, null,
                 instanceParams, supplementaryParams, false, false, null, UUID.randomUUID().toString(), null,
-            null, null, null, null);
+            null, null, null, null, "originalName");
     }
 
     protected ModelInfo createVfModuleModelInfo(String modelName, String modelVersion, String modelVersionId, String modelInvariantId, String modelCustomizationId, String modelCustomizationName) {
@@ -276,9 +279,9 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
     }
 
     protected VfModule createVfModuleForReplace(ModelInfo vfModuleModelInfo, String instanceName,
-        String lcpCloudRegionId, String tenantId, Boolean retainAssignments, Boolean retainVolumeGroups, Map<String, String> supplementaryParams) {
+        String lcpCloudRegionId, String tenantId, Boolean retainAssignments, Boolean retainVolumeGroups, List<UserParamNameAndValue> supplementaryParams) {
         return new VfModule( vfModuleModelInfo, instanceName, null, Action.Upgrade.name(), lcpCloudRegionId, null, tenantId,
-                null, supplementaryParams, true, null, null, UUID.randomUUID().toString(), null, null, retainAssignments, retainVolumeGroups, null);
+                null, supplementaryParams, true, null, null, UUID.randomUUID().toString(), null, null, retainAssignments, retainVolumeGroups, null, "originalName");
     }
 
     protected ModelInfo createVnfModelInfo(boolean isAlacarte) {
@@ -349,9 +352,11 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
         Map<String, Map<String, VfModule>> vfModules = new HashMap<>();
 
         List<Map<String, String>> instanceParams1 = ImmutableList.of((ImmutableMap.of("vmx_int_net_len", "24")));
-        VfModule vfModule1 = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", VF_MODULE_0_MODEL_VERSION_ID, VF_MODULE_0_MODEL_CUSTOMIZATION_NAME, instanceParams1, new HashMap<>(), (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vPE_BV_base" : null), null, isAlacarte);
+        VfModule vfModule1 = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", VF_MODULE_0_MODEL_VERSION_ID, VF_MODULE_0_MODEL_CUSTOMIZATION_NAME,
+            instanceParams1, emptyList(), (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vPE_BV_base" : null), null, isAlacarte, true);
         List<Map<String, String>> instanceParams2 = ImmutableList.of(vfModuleInstanceParamsMap);
-        VfModule vfModule2 = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", VF_MODULE_1_MODEL_VERSION_ID, VF_MODULE_1_MODEL_CUSTOMIZATION_NAME, instanceParams2, new HashMap<>(), (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vRE_BV_expansion": null), (isUserProvidedNaming ? "myVgName" : null), isAlacarte);
+        VfModule vfModule2 = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", VF_MODULE_1_MODEL_VERSION_ID, VF_MODULE_1_MODEL_CUSTOMIZATION_NAME,
+            instanceParams2, emptyList(), (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vRE_BV_expansion": null), (isUserProvidedNaming ? "myVgName" : null), isAlacarte, true);
 
         String vfModuleModelName = vfModule1.getModelInfo().getModelName();
         vfModules.put(vfModuleModelName, new LinkedHashMap<>());
@@ -361,7 +366,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
 
         Vnf vnf = new Vnf(vnfModelInfo, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", (isUserProvidedNaming ? VNF_NAME : null), Action.Create.name(),
                 "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", vnfInstanceParams,"lineOfBusinessName" , false, null, vfModules,
-                UUID.randomUUID().toString(), null, null, null);
+                UUID.randomUUID().toString(), null, null, null, "originalName");
 
         vnfs.put(vnf.getModelInfo().getModelName(), vnf);
         return vnfs;
@@ -393,7 +398,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
                 "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", null, "MOG", lcpCloudRegionId, null, tenantId,
                 null, null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, instanceParams, false, 1, false, false,
                 null, null, null, null, null, null,
-                new VidNotions(InstantiationUI.TRANSPORT_SERVICE, ModelCategory.Transport, InstantiationUI.TRANSPORT_SERVICE, InstantiationType.Macro)
+                new VidNotions(InstantiationUI.TRANSPORT_SERVICE, ModelCategory.Transport, InstantiationUI.TRANSPORT_SERVICE, InstantiationType.Macro), "originalName"
         );
         return serviceInstantiation;
     }
@@ -414,7 +419,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
                 details->new Network(createNetworkModelInfo(isALaCarte, details.modelCustomizationId), "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb",
                 details.name, Action.Create.name(),
                 "platformName", "mdt1", null, "88a6ca3ee0394ade9403f075db23167e", instanceParams,"lineOfBusinessName" ,
-                false, null, UUID.randomUUID().toString(), null, null, null));
+                false, null, UUID.randomUUID().toString(), null, null, null, "originalName"));
 //        I can't tell why compiler don't like the statement if it's only one line...
         return networkStream.collect(Collectors.toMap(network -> network.getModelInfo().getModelCustomizationId(), network -> network));
     }
@@ -430,7 +435,7 @@ public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests
         modelInfo.setModelVersion("10.0");
 
         return new InstanceGroup(modelInfo, (isUserProvidedNaming ? VNF_GROUP_NAME : null), action.name(), false, null, emptyMap(), UUID.randomUUID().toString(), null, null,
-            null);
+            null, "originalName");
     }
 
     protected ModelInfo createServiceModelInfo() {
index 7a6b94a..284efce 100644 (file)
@@ -23,8 +23,10 @@ package org.onap.vid.services;
 import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
 import static net.javacrumbs.jsonunit.JsonAssert.whenIgnoringPaths;
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals;
 import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.hasItem;
@@ -59,12 +61,14 @@ import static org.onap.vid.job.Job.JobStatus.PAUSE;
 import static org.onap.vid.job.Job.JobStatus.PENDING;
 import static org.onap.vid.job.Job.JobStatus.STOPPED;
 import static org.onap.vid.testUtils.TestUtils.generateRandomAlphaNumeric;
+import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -150,8 +154,6 @@ import org.testng.annotations.Test;
 @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class})
 public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseTest {
 
-
-
     @Mock
     private JobAdapter jobAdapterMock;
 
@@ -1054,7 +1056,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT
     public void whenLcpRegionNotEmpty_thenCloudRegionIdOfResourceIsLegacy() {
         String legacyCloudRegion = "legacyCloudRegion";
         Vnf vnf = new Vnf(new ModelInfo(), null, null, Action.Create.name(), null, "anyCloudRegion", legacyCloudRegion,
-                null, null, null, false, null, null, UUID.randomUUID().toString(), null, null, null);
+                null, null, null, false, null, null, UUID.randomUUID().toString(), null, null, null, "originalName");
         assertThat(vnf.getLcpCloudRegionId(), equalTo(legacyCloudRegion));
     }
 
@@ -1063,7 +1065,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT
         String legacyCloudRegion = "legacyCloudRegion";
         ServiceInstantiation service = new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null,
                 null, null, "anyCloudRegion", legacyCloudRegion, null, null, null, null, null, null, null, null, null,
-                false, 1,false, false, null, null, Action.Create.name(), UUID.randomUUID().toString(), null, null, null);
+                false, 1,false, false, null, null, Action.Create.name(), UUID.randomUUID().toString(), null, null, null, "originalName");
         assertThat(service.getLcpCloudRegionId(), equalTo(legacyCloudRegion));
     }
 
@@ -1087,7 +1089,7 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT
         return new ServiceInstantiation(new ModelInfo(), null, null, null, null, null, null,
                 null, null, null, null, null, null, null, null, null, null, null, null, null,
                 false, 1, false, isALaCarte, null, null, action.name(),
-                UUID.randomUUID().toString(), null, null, null);
+                UUID.randomUUID().toString(), null, null, null, "originalName");
     }
 
     @DataProvider
@@ -1221,7 +1223,8 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT
         String message = "Failed to create service instance";
         return new Object[][]{
                 {500, message},
-                {199, "{\"serviceException\":{\"messageId\":\"SVC2000\",\"text\":\"Error: " + message + "\"}}"}
+                {400, "{\"requestError\":{\"serviceException\":{\"messageId\":\"SVC0002\",\"text\":\"" + message + "\"}}}"},
+                {199, "{\"serviceException\":{\"messageId\":\"SVC2000\",\"text\":\"Error: " + message + "\"}}"},
         };
     }
 
@@ -1391,7 +1394,36 @@ public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseT
     {
         String path = asyncInstantiationBL.getVfModuleReplacePath("myService", "myVNF", "myVFModule");
         assertThat(path, equalTo("/serviceInstantiation/v7/serviceInstances/myService/vnfs/myVNF/vfModules/myVFModule/replace"));
+    }
 
+    @Test
+    public void whenCallClearStatusFromRequest_isFailedAndStatusAreRemoved() throws JsonProcessingException {
+        ServiceInstantiation serviceInstantiation = JACKSON_OBJECT_MAPPER.readValue(
+               "{"
+                + "    \"modelInfo\": {"
+                + "        \"modelType\": \"service\""
+                + "    },"
+                + "    \"isFailed\": true,"
+                + "    \"statusMessage\": \"some status\","
+                + "    \"vnfs\": {"
+                + "        \"vProbe_NC_VNF\": {"
+                + "            \"modelInfo\": {"
+                + "                \"modelType\": \"vnf\""
+                + "            },"
+                + "            \"isFailed\": true,"
+                + "            \"statusMessage\": \"other status\""
+                + "        }"
+                + "    }"
+                + "}",
+            ServiceInstantiation.class);
+        asyncInstantiationBL.clearStatusFromRequest(serviceInstantiation);
+        assertThat(serviceInstantiation, allOf(
+            jsonPartEquals("isFailed", false),
+            jsonPartEquals("statusMessage", null),
+            jsonPartEquals("vnfs.vProbe_NC_VNF.isFailed", false),
+            jsonPartEquals("vnfs.vProbe_NC_VNF.statusMessage", null)
+        ));
     }
 
+
 }
index f09ea31..de9fc2b 100644 (file)
 
 package org.onap.vid.services;
 
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.anEmptyMap;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.nullValue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
 import java.util.Map;
 import java.util.UUID;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.onap.vid.asdc.beans.Service;
 import org.onap.vid.dal.AsyncInstantiationRepository;
 import org.onap.vid.model.ModelUtil;
 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
 import org.onap.vid.model.serviceInstantiation.ServiceInstantiationTemplate;
 import org.onap.vid.model.serviceInstantiation.Vnf;
+import org.onap.vid.properties.Features;
 import org.onap.vid.testUtils.TestUtils;
+import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
+import org.togglz.core.manager.FeatureManager;
 
 public class InstantiationTemplatesServiceTest {
 
@@ -53,6 +68,9 @@ public class InstantiationTemplatesServiceTest {
     @Mock
     private ModelUtil modelUtil;
 
+    @Mock
+    private FeatureManager featureManager;
+
     @InjectMocks
     private InstantiationTemplatesService instantiationTemplatesService;
 
@@ -61,6 +79,11 @@ public class InstantiationTemplatesServiceTest {
         TestUtils.initMockitoMocks(this);
     }
 
+    @AfterMethod
+    public void resetMocks() {
+        reset(featureManager);
+    }
+
     @Test
     public void getJobRequestAsTemplate_whenIsCalled_asyncInstantiationRepositoryGetJobRequestIsInvoked() {
         UUID jobId = UUID.randomUUID();
@@ -99,4 +122,49 @@ public class InstantiationTemplatesServiceTest {
         assertThat(result, hasProperty("existingVRFCounterMap", anEmptyMap()));
     }
 
+    @DataProvider
+    public static Object[][] isTemplatesExistsByGivenServiceUuid() {
+        return new Object[][]{{"1",TRUE},
+                              {"3",FALSE}};
+    }
+
+    @Test(dataProvider = "isTemplatesExistsByGivenServiceUuid")
+    public void setInServicesTemplateValue_givenServiceWithServiceModelId_thenIsTemplateExistsIsEatherTrueOrFalse(String givenUuid, Boolean expectedTemplatesExist){
+
+        Service service = new Service();
+        service.setUuid(givenUuid);
+
+        Service newService = instantiationTemplatesService.setTemplateExistForService(service, ImmutableSet.of("1", "2"));
+        assertThat(newService.getIsInstantiationTemplateExists(), is(expectedTemplatesExist));
+    }
+
+    @Test
+    public void setTemplatesExistance_givenCollection__flagIsActive_thenSameCollectionReturnedWithTemplateExistsProperty(){
+        when(featureManager.isActive(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)).thenReturn(true);
+        when(asyncInstantiationRepository.getAllTemplatesServiceModelIds()).thenReturn(ImmutableSet.of("1", "2"));
+        Collection<Service> actualCollection = instantiationTemplatesService.setOnEachServiceIsTemplateExists(createGivenCollection());
+        assertThat(actualCollection, containsInAnyOrder(
+            allOf(hasProperty("uuid", is("1")), hasProperty("isInstantiationTemplateExists", is(true))),
+            allOf(hasProperty("uuid", is("3")), hasProperty("isInstantiationTemplateExists", is(false)))
+        ));
+    }
+
+    @Test
+    public void setTemplatesExistance_givenCollection_flagIsNotActive_thenTemplatesExistNotAdded(){
+        when(featureManager.isActive(Features.FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE)).thenReturn(false);
+        Collection<Service> actualCollection = instantiationTemplatesService.setOnEachServiceIsTemplateExists(createGivenCollection());
+        assertThat("was " + actualCollection, actualCollection, containsInAnyOrder(
+            allOf(hasProperty("uuid", is("1")), hasProperty("isInstantiationTemplateExists", is(false))),
+            allOf(hasProperty("uuid", is("3")), hasProperty("isInstantiationTemplateExists", is(false)))
+        ));
+    }
+
+    private Collection<Service> createGivenCollection(){
+        Service service1 = new Service();
+        Service service2 = new Service();
+        service1.setUuid("1");
+        service2.setUuid("3");
+        return ImmutableList.of(service1, service2);
+    }
+
 }
index efd9e2b..71d38b3 100644 (file)
 package org.onap.vid.services;
 
 import static com.google.common.collect.Maps.newHashMap;
+import static java.util.Collections.EMPTY_LIST;
+import static java.util.Collections.EMPTY_MAP;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonNodeAbsent;
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals;
@@ -41,7 +45,6 @@ import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -78,7 +81,7 @@ import org.onap.vid.mso.model.ModelInfo;
 import org.onap.vid.mso.model.NetworkInstantiationRequestDetails;
 import org.onap.vid.mso.model.ServiceDeletionRequestDetails;
 import org.onap.vid.mso.model.ServiceInstantiationRequestDetails;
-import org.onap.vid.mso.model.UserParamMap;
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue;
 import org.onap.vid.mso.model.VfModuleMacro;
 import org.onap.vid.mso.model.VfModuleOrVolumeGroupRequestDetails;
 import org.onap.vid.mso.model.VnfInstantiationRequestDetails;
@@ -163,7 +166,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     private void createMacroServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(boolean withVfmodules, boolean disabledHoming) throws IOException {
 
         ServiceInstantiation serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true,
-                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false),
+                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, EMPTY_LIST, false),
                 1,
                 false, PROJECT_NAME, true);
         URL resource;
@@ -181,7 +184,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
                 msoRequestBuilder.generateMacroServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016");
 
         String expected = IOUtils.toString(resource, "UTF-8");
-        MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result);
+        assertThat(result, jsonEquals(expected));
     }
 
     @Test
@@ -233,7 +236,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     }
 
     private ServiceInstantiation generateALaCarteServiceDeletionPayload() {
-        return generateMockAlaCarteServiceDeletionPayload(false, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API", "1234567890");
+        return generateMockAlaCarteServiceDeletionPayload(false, EMPTY_MAP, EMPTY_MAP, EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API", "1234567890");
     }
 
     @Test
@@ -255,7 +258,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     }
 
     private ServiceInstantiation generateServiceDeletionPayload() {
-        return generateMockServiceDeletionPayload(false, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API", "1234567890");
+        return generateMockServiceDeletionPayload(false, EMPTY_MAP, EMPTY_MAP, EMPTY_MAP, 1, true, PROJECT_NAME, false, "VNF_API", "1234567890");
     }
 
     @DataProvider
@@ -301,7 +304,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     public static Object[][] testBuildVnfInstanceParamsDataProvider(Method test) {
         return new Object[][]{
                 {
-                        Collections.EMPTY_LIST,
+                        EMPTY_LIST,
                         ImmutableList.of(
                                 ImmutableList.of(ImmutableMap.of("k1", "v1", "k2", "v2")),
                                 ImmutableList.of(ImmutableMap.of("k3", "v3", "k2", "v2"))
@@ -313,23 +316,23 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
                         ImmutableList.of(
                                 ImmutableList.of(ImmutableMap.of("k1", "v1", "k2", "v2")),
                                 ImmutableList.of(ImmutableMap.of("k3", "v3", "k2", "v2")),
-                                ImmutableList.of(Collections.EMPTY_MAP),
-                                Collections.singletonList(null)
+                                ImmutableList.of(EMPTY_MAP),
+                                singletonList(null)
                         ),
                         ImmutableList.of(ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "j1", "w1"))
                 },
                 {
-                        Collections.EMPTY_LIST,
+                        EMPTY_LIST,
                         Arrays.asList(null, null),
-                        Collections.EMPTY_LIST //mso is expect to empty list and not list with empty map
+                        EMPTY_LIST //mso is expect to empty list and not list with empty map
                 },
                 {
-                        ImmutableList.of(Collections.EMPTY_MAP),
+                        ImmutableList.of(EMPTY_MAP),
                         ImmutableList.of(
-                                ImmutableList.of(Collections.EMPTY_MAP),
-                                ImmutableList.of(Collections.EMPTY_MAP)
+                                ImmutableList.of(EMPTY_MAP),
+                                ImmutableList.of(EMPTY_MAP)
                         ),
-                        Collections.EMPTY_LIST //mso is expect to empty list and not list with empty map
+                        EMPTY_LIST //mso is expect to empty list and not list with empty map
                 }
         };
     }
@@ -347,24 +350,27 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     @DataProvider
     public static Object[][] vfModuleRequestDetails(Method test) {
         return new Object[][]{
-                {"cc3514e3-5a33-55df-13ab-12abad84e7cc", true, "/payload_jsons/vfmodule_instantiation_request.json"},
-                {null, true, "/payload_jsons/vfmodule_instantiation_request_without_volume_group.json"},
-                {null, false, "/payload_jsons/vfmodule_instantiation_request_without_instance_name.json"}
+                {"cc3514e3-5a33-55df-13ab-12abad84e7cc", true, false, "/payload_jsons/vfmodule_instantiation_request.json"},
+                {null, true, null, "/payload_jsons/vfmodule_instantiation_request_without_volume_group.json"},
+                {null, false, true, "/payload_jsons/vfmodule_instantiation_request_without_instance_name.json"}
         };
     }
 
     @Test(dataProvider = "vfModuleRequestDetails")
-    public void createVfModuleRequestDetails_detailsAreAsExpected(String volumeGroupInstanceId, boolean isUserProvidedNaming, String fileName) throws IOException {
+    public void createVfModuleRequestDetails_detailsAreAsExpected(String volumeGroupInstanceId, boolean isUserProvidedNaming, Boolean usePreload, String fileName) throws IOException {
 
         ModelInfo siModelInfo = createServiceModelInfo();
         ModelInfo vnfModelInfo = createVnfModelInfo(true);
         List<Map<String, String>> instanceParams = ImmutableList.of(ImmutableMap.of("vmx_int_net_len", "24",
                 "vre_a_volume_size_0", "120"));
-        Map<String, String> supplementaryParams = ImmutableMap.of("vre_a_volume_size_0", "100",
-                "availability_zone_0", "mtpocdv-kvm-az01");
+        List<UserParamNameAndValue> supplementaryParams = ImmutableList.of(
+            new UserParamNameAndValue("vre_a_volume_size_0", "100"),
+            new UserParamNameAndValue("availability_zone_0", "mtpocdv-kvm-az01")
+        );
+
         VfModule vfModule = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", "56e2b103-637c-4d1a-adc8-3a7f4a6c3240",
                 "72d9d1cd-f46d-447a-abdb-451d6fb05fa8", instanceParams, supplementaryParams,
-                (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vRE_BV_expansion" : null), "myVgName", true);
+                (isUserProvidedNaming ? "vmxnjr001_AVPN_base_vRE_BV_expansion" : null), "myVgName", true, usePreload);
 
         String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa";
         String vnfInstanceId = "bb3514e3-5a33-55df-13ab-12abad84e7bb";
@@ -378,26 +384,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
         final RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> result = msoRequestBuilder.generateVfModuleInstantiationRequest(
                 vfModule, siModelInfo, serviceInstanceId,
                 vnfModelInfo, vnfInstanceId, volumeGroupInstanceId, "pa0916", "VNF_API");
-        MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result);
-    }
-
-    @DataProvider
-    public static Object[][] expectedAggregatedParams() {
-        return new Object[][]{
-                {ImmutableMap.of("a", "b", "c", "d"), ImmutableMap.of("e", "f", "g", "h"), ImmutableList.of(ImmutableMap.of("c", "d", "a", "b", "e", "f", "g", "h"))},
-                {ImmutableMap.of("a", "b", "c", "g"), ImmutableMap.of("c", "d", "e", "f"), ImmutableList.of(ImmutableMap.of("a", "b", "c", "d", "e", "f"))},
-                {ImmutableMap.of(), ImmutableMap.of("c", "d", "e", "f"), ImmutableList.of(ImmutableMap.of("c", "d", "e", "f"))},
-                {ImmutableMap.of("a", "b", "c", "g"), ImmutableMap.of(), ImmutableList.of(ImmutableMap.of("a", "b", "c", "g"))},
-                {ImmutableMap.of(), ImmutableMap.of(), ImmutableList.of()},
-                {null, ImmutableMap.of(), ImmutableList.of()},
-                {ImmutableMap.of(), null, ImmutableList.of()},
-        };
-    }
-
-    @Test(dataProvider = "expectedAggregatedParams")
-    public void testAggregateInstanceParamsAndSuppFile(Map<String, String> instanceParams, Map<String, String> suppParams, List<UserParamMap<String, String>> expected) {
-        List<UserParamMap<String, String>> aggParams = msoRequestBuilder.aggregateAllInstanceParams(instanceParams, suppParams);
-        assertThat("Aggregated params are not as expected", aggParams, equalTo(expected));
+        assertThat(result, jsonEquals(expected).when(IGNORING_ARRAY_ORDER));
     }
 
     @Test
@@ -406,10 +393,11 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
         VfModule vfModule = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1",
                 "56e2b103-637c-4d1a-adc8-3a7f4a6c3240",
                 "72d9d1cd-f46d-447a-abdb-451d6fb05fa8",
-                Collections.emptyList(),
-                Collections.emptyMap(),
+                emptyList(),
+                emptyList(),
                 "vmxnjr001_AVPN_base_vRE_BV_expansion",
                 "myVgName",
+                true,
                 true);
         vfModule.getModelInfo().setModelInvariantId("ff5256d2-5a33-55df-13ab-12abad84e7ff");
         vfModule.getModelInfo().setModelVersion("1");
@@ -437,7 +425,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     @Test(dataProvider = "expectedNetworkRequestDetailsParameters")
     public void createNetworkRequestDetails_detailsAreAsExpected(String networkName, String filePath) throws IOException {
 
-        List<NetworkDetails> networkDetails = Collections.singletonList(new NetworkDetails(networkName, "ab153b6e-c364-44c0-bef6-1f2982117f04"));
+        List<NetworkDetails> networkDetails = singletonList(new NetworkDetails(networkName, "ab153b6e-c364-44c0-bef6-1f2982117f04"));
         final List<Network> networksList = new ArrayList<>(createNetworkList(null, networkDetails, true).values());
         ModelInfo siModelInfo = createServiceModelInfo();
         String serviceInstanceId = "aa3514e3-5a33-55df-13ab-12abad84e7aa";
@@ -495,7 +483,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     @Test
     public void checkIfNullProjectNameSentToMso() {
         ServiceInstantiation serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true,
-                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false),
+                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, EMPTY_LIST, false),
                 1,
                 false, null, false);
         RequestDetailsWrapper<ServiceInstantiationRequestDetails> result =
@@ -503,7 +491,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
         JsonNode jsonNode = new ObjectMapper().valueToTree(result.requestDetails);
         Assert.assertTrue(jsonNode.get("project").isNull());
         serviceInstantiationPayload = generateMockMacroServiceInstantiationPayload(true,
-                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false),
+                createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, EMPTY_LIST, false),
                 1,
                 false, "not null", false);
         result = msoRequestBuilder.generateMacroServiceInstantiationRequest(null, serviceInstantiationPayload, serviceInstantiationPayload.getInstanceName(), "az2016");
@@ -538,7 +526,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
                         "}";
         Vnf vnfDetails = new Vnf(createVnfModelInfo(true), "productFamily", "instanceName", Action.Delete.name(), "platform", "AAIAIC25", null,
                 "092eb9e8e4b7412e8787dd091bc58e86", null, null, false, "VNF_INSTANCE_ID", null, UUID.randomUUID().toString(), null, null,
-            null);
+            null, "originalName");
         RequestDetailsWrapper<VnfInstantiationRequestDetails> result =
                 msoRequestBuilder.generateDeleteVnfRequest(vnfDetails, "az2018");
         MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result);
@@ -569,7 +557,8 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
                         "    }" +
                         "  }" +
                         "}";
-        VfModule vfModuleDetails = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", VF_MODULE_0_MODEL_VERSION_ID, VF_MODULE_0_MODEL_CUSTOMIZATION_NAME, null, new HashMap<>(), "vmxnjr001_AVPN_base_vPE_BV_base", null, true);
+        VfModule vfModuleDetails = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", VF_MODULE_0_MODEL_VERSION_ID, VF_MODULE_0_MODEL_CUSTOMIZATION_NAME,
+            null, emptyList(), "vmxnjr001_AVPN_base_vPE_BV_base", null, true, true);
         RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> result =
                 msoRequestBuilder.generateDeleteVfModuleRequest(vfModuleDetails, "az2018");
         MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result);
@@ -636,16 +625,25 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     @Test
     public void generateReplaceVfModuleRequest_whenThereAreSupplementaryParams_thenTheyAreAddToUserParams() {
 
-        String expectedParams = "[{"
-            + "        \"vre_a_volume_size_0\" : \"100\","
-            + "        \"vmx_int_net_len\" : \"24\","
-            + "        \"availability_zone_0\": \"abc\""
-            + "      }]";
-
-        Map<String, String> supplementaryParams = ImmutableMap.of(
-            "vre_a_volume_size_0", "100",
-            "vmx_int_net_len", "24",
-            "availability_zone_0", "abc"
+        String expectedParams = "["
+            + "        {"
+            + "          \"name\": \"vre_a_volume_size_0\","
+            + "          \"value\": \"100\""
+            + "        },"
+            + "        {"
+            + "          \"name\": \"vmx_int_net_len\","
+            + "          \"value\": \"24\""
+            + "        },"
+            + "        {"
+            + "          \"name\": \"availability_zone_0\","
+            + "          \"value\": \"abc\""
+            + "        }"
+            + "     ]";
+
+        List<UserParamNameAndValue> supplementaryParams = ImmutableList.of(
+            new UserParamNameAndValue( "vre_a_volume_size_0", "100"),
+            new UserParamNameAndValue("vmx_int_net_len", "24"),
+            new UserParamNameAndValue("availability_zone_0", "abc")
         );
 
         assertThat(generatedVfModuleReplaceRequest(null, null, supplementaryParams),
@@ -662,7 +660,7 @@ public class MsoRequestBuilderTest extends AsyncInstantiationBaseTest {
     }
 
     private RequestDetailsWrapper<VfModuleOrVolumeGroupRequestDetails> generatedVfModuleReplaceRequest(
-        Boolean retainAssignments, Boolean retainVolumeGroups, Map<String, String> supplementaryParams) {
+        Boolean retainAssignments, Boolean retainVolumeGroups, List<UserParamNameAndValue> supplementaryParams) {
         when(featureManager.isActive(Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST)).thenReturn(true);
         when(aaiClient.getCloudOwnerByCloudRegionId("regionOne")).thenReturn("irma-aic");
 
diff --git a/vid-app-common/src/test/java/org/onap/vid/services/UserParamsContainerTest.kt b/vid-app-common/src/test/java/org/onap/vid/services/UserParamsContainerTest.kt
new file mode 100644 (file)
index 0000000..511c4e5
--- /dev/null
@@ -0,0 +1,57 @@
+package org.onap.vid.services
+
+import org.hamcrest.CoreMatchers.equalTo
+import org.hamcrest.MatcherAssert
+import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.UserParamNameAndValue
+import org.testng.annotations.DataProvider
+import org.testng.annotations.Test
+
+class UserParamsContainerTest {
+
+    @DataProvider
+    fun userParamsDataProvider(): Array<Array<Any?>>? {
+        return arrayOf(
+            arrayOf<Any?>(
+                mapOf("a" to "b", "c" to "d"),
+                listOf(UserParamNameAndValue("e", "f"), UserParamNameAndValue("g", "h")),
+                mapOf("c" to "d", "a" to "b", "e" to "f", "g" to "h")
+            ),
+            arrayOf<Any?>(
+                mapOf("a" to "b", "c" to "g"),
+                listOf(UserParamNameAndValue("c", "d") , UserParamNameAndValue("e", "f")),
+                mapOf("c" to "d", "a" to "b", "e" to "f")
+            ),
+            arrayOf<Any?>(
+                emptyMap<String,String>(),
+                listOf(UserParamNameAndValue("c", "d"), UserParamNameAndValue("e", "f")),
+                mapOf("c" to "d", "e" to "f")
+            ),
+            arrayOf<Any?>(
+                mapOf("a" to "b", "c" to "d"),
+                emptyList<UserParamNameAndValue>(),
+                mapOf("a" to "b", "c" to "d")
+            ),
+            arrayOf<Any?>(
+                emptyMap<String,String>(),
+                emptyList<UserParamNameAndValue>(),
+                emptyMap<String,String>()
+            ),
+            arrayOf(
+                null,
+                emptyList<UserParamNameAndValue>(),
+                emptyMap<String,String>()
+            ),
+            arrayOf<Any?>(
+                emptyMap<String,String>(),
+                null,
+                emptyMap<String,String>()
+            )
+        )
+    }
+
+    @Test(dataProvider = "userParamsDataProvider")
+    fun testUserParamsConvertorCtor(instanceParams: Map<String, String>?, suppParams: List<UserParamNameAndValue>?, expected: Map<String, String>) {
+        val aggParams: Map<String, String> = UserParamsContainer(instanceParams, suppParams).params
+        MatcherAssert.assertThat("Aggregated params are not as expected", aggParams, equalTo(expected))
+    }
+}
\ No newline at end of file
index 862b8db..71f7ee0 100644 (file)
@@ -21,9 +21,7 @@
 package org.onap.vid.testUtils;
 
 import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper;
-import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
 import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors;
 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
 import static org.apache.commons.text.CharacterPredicates.DIGITS;
@@ -52,7 +50,9 @@ import java.lang.reflect.Field;
 import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Predicate;
 import javax.ws.rs.client.Client;
@@ -61,7 +61,6 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
@@ -174,15 +173,27 @@ public class TestUtils {
     }
 
     public static String[] allPropertiesOf(Class<?> aClass) {
-        return Arrays.stream(getPropertyDescriptors(aClass))
+        return getPropertyDescriptorsRecursively(aClass).stream()
             .map(PropertyDescriptor::getDisplayName)
+            .distinct()
             .toArray(String[]::new);
     }
 
+    private static List<PropertyDescriptor> getPropertyDescriptorsRecursively(Class<?> aClass) {
+        List<PropertyDescriptor> result = new LinkedList<>();
+
+        for (Class<?> i = aClass; i != null && i != Object.class; i = i.getSuperclass()) {
+            Collections.addAll(result, getPropertyDescriptors(i));
+        }
+
+        return result;
+    }
+
     private static <T> List<String> allStringPropertiesOf(T object) {
-        return Arrays.stream(getPropertyDescriptors(object.getClass()))
+        return getPropertyDescriptorsRecursively(object.getClass()).stream()
             .filter(descriptor -> descriptor.getPropertyType().isAssignableFrom(String.class))
             .map(PropertyDescriptor::getDisplayName)
+            .distinct()
             .collect(toList());
     }
 
@@ -221,16 +232,15 @@ public class TestUtils {
      * @return The modified object
      */
     public static <T> T setStringsInStringProperties(T object) {
-        try {
-            final List<String> stringFields = allStringPropertiesOf(object);
-
-            BeanUtils.populate(object, stringFields.stream()
-                .collect(toMap(identity(), identity())));
+        allStringPropertiesOf(object).forEach(it -> {
+            try {
+                FieldUtils.writeField(object, it, it, true);
+            } catch (IllegalAccessException e) {
+                // YOLO
+            }
+        });
 
-            return object;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+        return object;
     }
 
     public static void registerCloudConfigurationValueGenerator() {
diff --git a/vid-app-common/src/test/resources/example.features.properties b/vid-app-common/src/test/resources/example.features.properties
new file mode 100644 (file)
index 0000000..e8ac3eb
--- /dev/null
@@ -0,0 +1 @@
+FLAG_1810_AAI_LOCAL_CACHE=true
\ No newline at end of file
index 642c2aa..a4f609a 100644 (file)
@@ -10,6 +10,7 @@
             "instanceId": "VF_MODULE_INSTANCE_ID",
             "action": "Create",
             "lcpCloudRegionId": "AAIAIC25",
+            "legacyRegion": "some legacy region",
             "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
             "modelInfo": {
               "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091",
@@ -36,6 +37,7 @@
             "provStatus": "Prov Status",
             "inMaint": false,
             "lcpCloudRegionId": "AAIAIC25",
+            "legacyRegion": "some legacy region",
             "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
             "modelInfo": {
               "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
@@ -59,6 +61,7 @@
             "provStatus": "Prov Status",
             "inMaint": false,
             "lcpCloudRegionId": "AAIAIC25",
+            "legacyRegion": "some legacy region",
             "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
             "modelInfo": {
               "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
index d215a43..16d369b 100644 (file)
   "rollbackOnFailure": false,
   "isALaCarte": true,
   "collectionResources": {},
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "vidNotions": {
     "instantiationUI": "legacy",
     "modelCategory": "other",
index 91f80e9..5c258f6 100644 (file)
@@ -36,7 +36,7 @@
       "retainAssignments": false,
       "usePreload" : true,
       "userParams": [],
-      "testApi": "VNF_API"
+      "testApi": "GR_API"
     },
     "modelInfo": {
       "modelType": "vfModule",
index 1bce760..e5e3e9f 100644 (file)
       }
     ],
     "requestParameters": {
-      "usePreload": true,
-      "userParams": [{
-        "vre_a_volume_size_0" : "100",
-        "vmx_int_net_len" : "24",
-        "availability_zone_0": "mtpocdv-kvm-az01"
-      }],
+      "usePreload": false,
+      "userParams": [
+        {
+          "name": "vre_a_volume_size_0",
+          "value": "100"
+        },
+        {
+          "name": "vmx_int_net_len",
+          "value": "24"
+        },
+        {
+          "name": "availability_zone_0",
+          "value": "mtpocdv-kvm-az01"
+        }
+     ],
       "testApi" : "VNF_API"
     }
   }
index 1c0d2b9..026c16f 100644 (file)
     ],
     "requestParameters": {
       "usePreload": true,
-      "userParams": [{
-        "vre_a_volume_size_0" : "100",
-        "vmx_int_net_len" : "24",
-        "availability_zone_0": "mtpocdv-kvm-az01"
-      }],
+      "userParams": [
+        {
+          "name": "vre_a_volume_size_0",
+          "value": "100"
+        },
+        {
+          "name": "vmx_int_net_len",
+          "value": "24"
+        },
+        {
+          "name": "availability_zone_0",
+          "value": "mtpocdv-kvm-az01"
+        }
+      ],
       "testApi" : "VNF_API"
     }
   }
index 3581a47..87db583 100644 (file)
       }
     ],
     "requestParameters": {
-      "usePreload": true,
-      "userParams": [{
-        "vre_a_volume_size_0" : "100",
-        "vmx_int_net_len" : "24",
-        "availability_zone_0": "mtpocdv-kvm-az01"
-      }],
+      "usePreload": false,
+      "userParams": [
+        {
+          "name": "vre_a_volume_size_0",
+          "value": "100"
+        },
+        {
+          "name": "vmx_int_net_len",
+          "value": "24"
+        },
+        {
+          "name": "availability_zone_0",
+          "value": "mtpocdv-kvm-az01"
+        }
+      ],
       "testApi" : "VNF_API"
     }
   }
diff --git a/vid-app-common/src/test/resources/responses/aai/listServicesByOwningEntity.json b/vid-app-common/src/test/resources/responses/aai/listServicesByOwningEntity.json
new file mode 100644 (file)
index 0000000..a97a74a
--- /dev/null
@@ -0,0 +1,97 @@
+{
+  "owning-entity": [
+    {
+      "owning-entity-id": "43b8a85a-0421-4265-9069-117dd6526b8a",
+      "owning-entity-name": "Melissa",
+      "resource-version": "1527418700853",
+      "relationship-list": {
+        "relationship": [
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.BelongsTo",
+            "related-link": "/aai/v12/business/customers/customer/256cddb4-3aa1-43cc-a08f-315bb50b275e/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/af9d52f9-13b2-4657-a198-463677f82dc0",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "256cddb4-3aa1-43cc-a08f-315bb50b275e"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "MSO-dev-service-type"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "af9d52f9-13b2-4657-a198-463677f82dc0"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "xbghrftgr_shani"
+              }
+            ]
+          },
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.BelongsTo",
+            "related-link": "/aai/v12/business/customers/customer/e02fd6f2-7fc2-434b-a92d-15abdb24b68d/service-subscriptions/service-subscription/JUST-another-service-type/service-instances/service-instance/49769492-5def-4c89-8e73-b236f958fa40",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "e02fd6f2-7fc2-434b-a92d-15abdb24b68d"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "JUST-another-service-type"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "49769492-5def-4c89-8e73-b236f958fa40"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "fghghfhgf"
+              }
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "owning-entity-id": "26dcc4aa-725a-447d-8346-aa26dfaa4eb7",
+      "owning-entity-name": "Kobe",
+      "resource-version": "1527418700844",
+      "relationship-list": {
+        "relationship": [
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.BelongsTo",
+            "related-link": "/aai/v12/business/customers/customer/256cddb4-3aa1-43cc-a08f-315bb50b275e/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/1d8fd482-2f53-4d62-a7bd-20e4bab14c45",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "256cddb4-3aa1-43cc-a08f-315bb50b275e"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "MSO-dev-service-type"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "1d8fd482-2f53-4d62-a7bd-20e4bab14c45"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "Bryant"
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/vid-app-common/src/test/resources/responses/aai/listServicesByProject.json b/vid-app-common/src/test/resources/responses/aai/listServicesByProject.json
new file mode 100644 (file)
index 0000000..6d6b09f
--- /dev/null
@@ -0,0 +1,95 @@
+{
+  "project": [
+    {
+      "project-name": "x1",
+      "resource-version": "1527026201826",
+      "relationship-list": {
+        "relationship": [
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.Uses",
+            "related-link": "/aai/v12/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Emanuel/service-instances/service-instance/3f826016-3ac9-4928-9561-beee75fd91d5",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "Emanuel"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "3f826016-3ac9-4928-9561-beee75fd91d5"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "Lital_SRIOV2_001"
+              }
+            ]
+          }
+        ]
+      }
+    },
+    {
+      "project-name": "y2",
+      "resource-version": "1527026341826",
+      "relationship-list": {
+        "relationship": [
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.BelongsTo",
+            "related-link": "/aai/v12/business/customers/customer/3d15d7ea-4174-49b6-89ec-e569381f7231/service-subscriptions/service-subscription/vMOG/service-instances/service-instance/7e4f8130-5dee-47c4-8770-1abc5f5ded83",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "3d15d7ea-4174-49b6-89ec-e569381f7231"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "vMOG"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "7e4f8130-5dee-47c4-8770-1abc5f5ded83"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "justAname"
+              }
+            ]
+          },
+          {
+            "related-to": "service-instance",
+            "relationship-label": "org.onap.relationships.inventory.Uses",
+            "related-link": "/aai/v12/business/customers/customer/a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb/service-subscriptions/service-subscription/Yoda/service-instances/service-instance/ff2d9326-1ef5-4760-aba0-0eaf372ae675",
+            "relationship-data": [
+              {
+                "relationship-key": "customer.global-customer-id",
+                "relationship-value": "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"
+              },
+              {
+                "relationship-key": "service-subscription.service-type",
+                "relationship-value": "Yoda"
+              },
+              {
+                "relationship-key": "service-instance.service-instance-id",
+                "relationship-value": "ff2d9326-1ef5-4760-aba0-0eaf372ae675"
+              }
+            ],
+            "related-to-property": [
+              {
+                "property-key": "service-instance.service-instance-name",
+                "property-value": "anotherName"
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+}
index 19ee1fb..ce5339b 100755 (executable)
@@ -4,7 +4,7 @@
 
 major=6
 minor=0
-patch=0
+patch=3
 
 base_version=${major}.${minor}.${patch}
 
index 16a756c..77d54db 100644 (file)
@@ -47,7 +47,7 @@
         <dependency>
             <groupId>com.aventstack</groupId>
             <artifactId>extentreports</artifactId>
-            <version>4.0.9</version>
+            <version>3.1.5</version>
         </dependency>
 
         <dependency>
index b3be16a..dd08eb3 100644 (file)
@@ -171,9 +171,6 @@ public abstract class SetupCDTest extends DriverFactory {
 
        public static void navigateToUrl(String url)  {
                try {
-                       System.out.println("Deleting cookies...");
-                       deleteCookies();
-
                        System.out.println("Navigating to URL : " + url);
                        getDriver().navigate().to(url);
                        GeneralUIUtils.waitForLoader();
index dd632d2..56fd2d3 100644 (file)
@@ -374,7 +374,7 @@ public final class GeneralUIUtils {
        }
 
        public static void waitForLoader(int timeOut) {
-               newWait(timeOut).until(ExpectedConditions.invisibilityOfElementLocated(By.className("sdc-loader-background")));
+               newWait(timeOut).until(ExpectedConditions.invisibilityOfElementLocated(By.className("custom-loader-background")));
        }
 
        public static void findComponentAndClick(String resourceName) throws Exception {
index 7c4ce03..0888bd9 100644 (file)
@@ -11,22 +11,6 @@ public abstract class BaseMSOPreset extends BasePreset {
     public static final String DEFAULT_INSTANCE_ID = "f8791436-8d55-4fde-b4d5-72dd2cf13cfb";
     protected String cloudOwner = DEFAULT_CLOUD_OWNER;
 
-    public static String getRequestBodyWithTestApiOnly() {
-        if (Features.FLAG_ADD_MSO_TESTAPI_FIELD.isActive()) {
-            return "" +
-                    "{" +
-                    "  \"requestDetails\": { " +
-                    "    \"requestParameters\": { " +
-                    "      \"testApi\": \"VNF_API\" " +
-                    "    } " +
-                    "  } " +
-                    "} " +
-                    "";
-        } else {
-            return null;
-        }
-    }
-
     protected String addCloudOwnerIfNeeded() {
         return Features.FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST.isActive() ?
             "\"cloudOwner\": \"" + cloudOwner + "\"," : "";
index ae921fd..88ea09a 100644 (file)
@@ -1,18 +1,31 @@
 package org.onap.simulator.presetGenerator.presets.aai;
 
 import com.google.common.collect.ImmutableMap;
-import org.onap.simulator.presetGenerator.presets.BasePresets.BaseAAIPreset;
-import org.springframework.http.HttpMethod;
-
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseAAIPreset;
+import org.springframework.http.HttpMethod;
 
 public class PresetAAIGetModelsByOwningEntity extends BaseAAIPreset {
-    String oeName;
+
+    private static final String DEFAULT_OWNING_ENTITY_ID = "43b8a85a-0421-4265-9069-117dd6526b8a";
+    private static final String DEFAULT_SUBSCRIBER_ID = "CAR_2020_ER";
+
+    private String oeName;
+    private String oeId;
+    private String subscriberId;
 
     public PresetAAIGetModelsByOwningEntity(String oeName) {
         this.oeName = oeName;
+        this.oeId = DEFAULT_OWNING_ENTITY_ID;
+        this.subscriberId = DEFAULT_SUBSCRIBER_ID;
+    }
+
+    public PresetAAIGetModelsByOwningEntity(String oeName, String oeId, String subscriberId) {
+        this.oeName = oeName;
+        this.oeId = oeId;
+        this.subscriberId = subscriberId;
     }
 
     @Override
@@ -37,7 +50,7 @@ public class PresetAAIGetModelsByOwningEntity extends BaseAAIPreset {
         return "{" +
                 "      \"owning-entity\": [" +
                 "        {" +
-                "          \"owning-entity-id\": \"43b8a85a-0421-4265-9069-117dd6526b8a\"," +
+            "          \"owning-entity-id\": \"" + oeId + "\"," +
                 "          \"owning-entity-name\": \"" + oeName + "\"," +
                 "          \"resource-version\": \"1527418700853\"," +
                 "          \"relationship-list\": {" +
@@ -45,11 +58,11 @@ public class PresetAAIGetModelsByOwningEntity extends BaseAAIPreset {
                 "              {" +
                 "                \"related-to\": \"service-instance\"," +
                 "                \"relationship-label\": \"org.onap.relationships.inventory.BelongsTo\"," +
-                "                \"related-link\": \"/aai/v12/business/customers/customer/CAR_2020_ER/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/af9d52f9-13b2-4657-a198-463677f82dc0\"," +
+            "                \"related-link\": \"/aai/v12/business/customers/customer/" + subscriberId + "/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/af9d52f9-13b2-4657-a198-463677f82dc0\"," +
                 "                \"relationship-data\": [" +
                 "                  {" +
                 "                    \"relationship-key\": \"customer.global-customer-id\"," +
-                "                    \"relationship-value\": \"CAR_2020_ER\"" +
+            "                    \"relationship-value\": \"" + subscriberId + "\"" +
                 "                  }," +
                 "                  {" +
                 "                    \"relationship-key\": \"service-subscription.service-type\"," +
@@ -70,11 +83,11 @@ public class PresetAAIGetModelsByOwningEntity extends BaseAAIPreset {
                 "              {" +
                 "                \"related-to\": \"service-instance\"," +
                 "                \"relationship-label\": \"org.onap.relationships.inventory.BelongsTo\"," +
-                "                \"related-link\": \"/aai/v12/business/customers/customer/CAR_2020_ER/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/49769492-5def-4c89-8e73-b236f958fa40\"," +
+            "                \"related-link\": \"/aai/v12/business/customers/customer/" + DEFAULT_SUBSCRIBER_ID + "/service-subscriptions/service-subscription/MSO-dev-service-type/service-instances/service-instance/49769492-5def-4c89-8e73-b236f958fa40\"," +
                 "                \"relationship-data\": [" +
                 "                  {" +
                 "                    \"relationship-key\": \"customer.global-customer-id\"," +
-                "                    \"relationship-value\": \"CAR_2020_ER\"" +
+            "                    \"relationship-value\": \"" + DEFAULT_SUBSCRIBER_ID + "\"" +
                 "                  }," +
                 "                  {" +
                 "                    \"relationship-key\": \"service-subscription.service-type\"," +
index 0c81364..ad7bd0b 100644 (file)
@@ -23,7 +23,7 @@ public abstract class PresetMSOBaseDeleteWithCloudConfiguration extends PresetMS
                 "      \"requestorId\": \"us16807000\"" +
                 "    }," +
                 "    \"requestParameters\": {" +
-                "      \"testApi\": \"VNF_API\"" +
+                "      \"testApi\": \"GR_API\"" +
                 "    }," +
                 "    \"cloudConfiguration\": {" +
                 "      \"lcpCloudRegionId\": \"hvf6\"," +
index 0b7c651..835621a 100644 (file)
@@ -70,7 +70,7 @@ public class PresetMSOCreateNetworkALaCarte5G extends PresetMSOBaseCreateInstanc
                 "      }" +
                 "    ]," +
                 "    \"requestParameters\": {" +
-                "      \"testApi\": \"VNF_API\"," +
+                "      \"testApi\": \"GR_API\"," +
                 "      \"userParams\": []" +
                 "    }" +
                 "  }" +
index fcad03c..fd70723 100644 (file)
@@ -38,7 +38,7 @@ public class PresetMSOCreateNetworkALaCarteOldViewEdit extends PresetMSOBaseCrea
                 "          \"modelCustomizationName\": \"AIC30_CONTRAIL_BASIC 0\"" +
                 "        }," +
                 "        \"requestParameters\": {" +
-                "          \"testApi\": \"VNF_API\"," +
+                "          \"testApi\": \"GR_API\"," +
                 "          \"userParams\": []" +
                 "        }," +
                 "        \"cloudConfiguration\": {" +
index 180aaef..a0867e5 100644 (file)
@@ -44,7 +44,7 @@ public class PresetMSOCreateServiceInstanceAlacarte extends PresetMSOCreateServi
                 "      \"requestorId\": \""+this.requestorId+"\"" +
                 "    }," +
                 "    \"requestParameters\": {" +
-                "      \"testApi\": \"VNF_API\"," +
+                "      \"testApi\": \"GR_API\"," +
                 "      \"subscriptionServiceType\": \"TYLER SILVIA\"," +
                 "      \"aLaCarte\": true," +
                 "      \"userParams\": []" +
index f80f6bb..f1de64f 100644 (file)
@@ -42,7 +42,7 @@ public class PresetMSOCreateServiceInstanceGen2AlacarteService extends PresetMSO
                 "      \"requestorId\": \"us16807000\" " +
                 "    }, " +
                 "    \"requestParameters\": { " +
-                "      \"testApi\": \"VNF_API\", " +
+                "      \"testApi\": \"GR_API\", " +
                 "      \"subscriptionServiceType\": \"TYLER SILVIA\", " +
                 "      \"aLaCarte\": true, " +
                 "      \"userParams\": [] " +
index 28705ad..fcec155 100644 (file)
@@ -50,7 +50,7 @@ public class PresetMSOCreateServiceInstanceGen2WithNamesAlacarteGroupingService
                 "      \"requestorId\": \"" + userId + "\" " +
                 "    }, " +
                 "    \"requestParameters\": { " +
-                "      \"testApi\": \"VNF_API\", " +
+                "      \"testApi\": \"GR_API\", " +
                 "      \"subscriptionServiceType\": \"TYLER SILVIA\", " +
                 "      \"aLaCarte\": true, " +
                 "      \"userParams\": [] " +
index cc33a3b..4ad26cc 100644 (file)
@@ -47,7 +47,7 @@ public class PresetMSOCreateServiceInstanceGen2WithNamesAlacarteService extends
                 "      \"requestorId\": \"us16807000\" " +
                 "    }, " +
                 "    \"requestParameters\": { " +
-                "      \"testApi\": \"VNF_API\", " +
+                "      \"testApi\": \"GR_API\", " +
                 "      \"subscriptionServiceType\": \"TYLER SILVIA\", " +
                 "      \"aLaCarte\": true, " +
                 "      \"userParams\": [] " +
index f203a7d..9ace359 100644 (file)
@@ -66,7 +66,7 @@ public class PresetMSOCreateVNFInstanceOnlyRelatedServiceInstance extends Preset
                 "    ]," +
                 "    \"requestParameters\": {" +
                 "      \"userParams\": []," +
-                "      \"testApi\": \"VNF_API\"" +
+                "      \"testApi\": \"GR_API\"" +
                 "    }" +
                 "  }" +
                 "}";
index 89744a7..185c4bf 100644 (file)
@@ -67,12 +67,16 @@ public class PresetMSOCreateVfModuleALaCarteE2E extends PresetMSOCreateVfModuleB
             + "            }" + addRelatedInstance()
             + "        ],"
             + "        \"requestParameters\": {"
-            + "            \"userParams\": [{"
-            + "                    \"param\": \"ABCD\","
-            + "                    \"vnf_instance_name\": \"sample\""
+            + "               \"usePreload\": false,"
+            + "               \"userParams\": [{"
+            + "                    \"name\": \"param\","
+            + "                    \"value\": \"ABCD\""
+            + "                }, {"
+            + "                    \"name\": \"vnf_instance_name\","
+            + "                    \"value\": \"sample\""
             + "                }"
             + "            ],"
-            + "            \"testApi\": \"VNF_API\""
+            + "            \"testApi\": \"GR_API\""
             + "        }"
             + "    }"
             + "}";
index 5a0b752..9d9984a 100644 (file)
@@ -93,14 +93,23 @@ public class PresetMSOCreateVfModuleWithVolumeGroupALaCarteCypress extends Prese
                 "    ]," +
                 "    \"requestParameters\":{" +
                addTestApi()+
-                "       \"userParams\":[{" +
-                "          \"2017488_pasqualevpe0_vnf_instance_name\":\"mtnj309me6\"," +
-                "          \"2017488_pasqualevpe0_vnf_config_template_version\":\"17.2\"," +
-                "          \"pasqualevpe0_bandwidth\":\"10\"," +
-                "          \"2017488_pasqualevpe0_AIC_CLLI\":\"ATLMY8GA\"," +
-                "          \"pasqualevpe0_bandwidth_units\":\"Gbps\"" +
-                "        }" +
-                "      ]," +
+                "\"userParams\": [{"
+            + "                    \"name\": \"pasqualevpe0_bandwidth\","
+            + "                    \"value\": \"10\""
+            + "                }, {"
+            + "                    \"name\": \"2017488_pasqualevpe0_vnf_instance_name\","
+            + "                    \"value\": \"mtnj309me6\""
+            + "                }, {"
+            + "                    \"name\": \"2017488_pasqualevpe0_vnf_config_template_version\","
+            + "                    \"value\": \"17.2\""
+            + "                }, {"
+            + "                    \"name\": \"2017488_pasqualevpe0_AIC_CLLI\","
+            + "                    \"value\": \"ATLMY8GA\""
+            + "                }, {"
+            + "                    \"name\": \"pasqualevpe0_bandwidth_units\","
+            + "                    \"value\": \"Gbps\""
+            + "                }"
+            + "            ]," +
                 "      \"usePreload\":true" +
                 "    }" +
                 "  }" +
index dba42f3..07839ba 100644 (file)
@@ -40,6 +40,7 @@ public class PresetMSOCreateVnfALaCarteE2E extends PresetMSOCreateVnfBase {
             + "            \"tenantId\": \"092eb9e8e4b7412e8787dd091bc58e86\""
             + "        },"
             + "        \"requestInfo\": {"
+            + "            \"productFamilyId\":\"e433710f-9217-458d-a79d-1c7aff376d89\","
             + "            \"source\": \"VID\","
             + "            \"suppressRollback\": false,"
             + "            \"requestorId\": \""+requestorId+"\""
@@ -59,7 +60,7 @@ public class PresetMSOCreateVnfALaCarteE2E extends PresetMSOCreateVnfBase {
             + "        ],"
             + "        \"requestParameters\": {"
             + "            \"userParams\": [],"
-            + "            \"testApi\": \"VNF_API\""
+            + "            \"testApi\": \"GR_API\""
             + "        }"
             + "    }"
             + "}";
index afdb3f4..bca049d 100644 (file)
@@ -30,7 +30,7 @@ public class PresetMSOCreateVnfALaCarteServiceCypress2 extends PresetMSOCreateVn
                     "\"modelType\":\"vnf\"," +
                     "\"modelVersion\":\"4.0\"}," +
                 "\"requestParameters\":{" +
-                    "\"testApi\": \"VNF_API\", " +
+                    "\"testApi\": \"GR_API\", " +
                     "\"userParams\":[]" +
                 "}," +
                 "\"relatedInstanceList\":[" +
index ac2d6f4..41e6748 100644 (file)
@@ -45,7 +45,7 @@ public class PresetMSOCreateVnfGroup extends PresetMSOBaseCreateInstancePost {
                 "      }" +
                 "    ]," +
                 "    \"requestParameters\": {" +
-                "      \"testApi\": \"VNF_API\", " +
+                "      \"testApi\": \"GR_API\", " +
                 "      \"userParams\": []" +
                 "    }" +
                 "  }" +
index d5faa3f..131fe80 100644 (file)
@@ -55,7 +55,7 @@ public class PresetMSOCreateVnfVlanTagging extends PresetMSOBaseCreateInstancePo
                 "    }," +
                 "    \"requestParameters\": {" +
                 "      \"userParams\": []," +
-                "      \"testApi\": \"VNF_API\"" +
+                "      \"testApi\": \"GR_API\"" +
                 "    }," +
                 "    \"relatedInstanceList\": [{" +
                 "        \"relatedInstance\": {" +
index b20d462..0fb9179 100644 (file)
@@ -37,7 +37,7 @@ public class PresetMSODeleteALaCarteService extends PresetMSODeleteService {
                 "      \"requestorId\": \"us16807000\"" +
                 "    }," +
                 "    \"requestParameters\": {" +
-                "       \"testApi\": \"VNF_API\","+
+                "       \"testApi\": \"GR_API\","+
                 "      \"aLaCarte\": true" +
                 "    }" +
                 "  }" +
index 1d3b8c0..4c667d9 100644 (file)
@@ -1,13 +1,12 @@
 package org.onap.simulator.presetGenerator.presets.mso;
 
-import com.google.common.collect.ImmutableMap;
-import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
-import org.springframework.http.HttpMethod;
+import static java.util.Collections.singletonList;
 
+import com.google.common.collect.ImmutableMap;
 import java.util.List;
 import java.util.Map;
-
-import static java.util.Collections.singletonList;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
+import org.springframework.http.HttpMethod;
 
 public class PresetMSOOrchestrationRequestsGet5GServiceInstanceAndNetwork extends BaseMSOPreset {
 
@@ -82,7 +81,7 @@ public class PresetMSOOrchestrationRequestsGet5GServiceInstanceAndNetwork extend
                 "          \"requestParameters\": {" +
                 "            \"subscriptionServiceType\": \"TYLER SILVIA\"," +
                 "            \"aLaCarte\": true," +
-                "            \"testApi\": \"VNF_API\"" +
+                "            \"testApi\": \"GR_API\"" +
                 "          }," +
                 "          \"project\": {" +
                 "            \"projectName\": \"WATKINS\"" +
index 8524d92..ee4fd3a 100644 (file)
@@ -1,13 +1,12 @@
 package org.onap.simulator.presetGenerator.presets.mso;
 
-import com.google.common.collect.ImmutableMap;
-import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
-import org.springframework.http.HttpMethod;
+import static java.util.Collections.singletonList;
 
+import com.google.common.collect.ImmutableMap;
 import java.util.List;
 import java.util.Map;
-
-import static java.util.Collections.singletonList;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
+import org.springframework.http.HttpMethod;
 
 public class PresetMSOOrchestrationRequestsGetByRequestId extends BaseMSOPreset {
 
@@ -57,7 +56,7 @@ public class PresetMSOOrchestrationRequestsGetByRequestId extends BaseMSOPreset
                 "      \"requestParameters\": {" +
                 "        \"subscriptionServiceType\": \"Kennedy\"," +
                 "        \"aLaCarte\": true," +
-                "        \"testApi\": \"VNF_API\"" +
+                "        \"testApi\": \"GR_API\"" +
                 "      }," +
                 "      \"project\": {" +
                 "        \"projectName\": \"Kennedy\"" +
index 9217765..cbce5a2 100644 (file)
@@ -1,13 +1,12 @@
 package org.onap.simulator.presetGenerator.presets.mso;
 
-import com.google.common.collect.ImmutableMap;
-import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
-import org.springframework.http.HttpMethod;
+import static java.util.Collections.singletonList;
 
+import com.google.common.collect.ImmutableMap;
 import java.util.List;
 import java.util.Map;
-
-import static java.util.Collections.singletonList;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
+import org.springframework.http.HttpMethod;
 
 public class PresetMSOOrchestrationRequestsGetByServiceInstanceId extends BaseMSOPreset {
 
@@ -68,7 +67,7 @@ public class PresetMSOOrchestrationRequestsGetByServiceInstanceId extends BaseMS
                 "      \"requestParameters\": {" +
                 "        \"subscriptionServiceType\": \"Kennedy\"," +
                 "        \"aLaCarte\": true," +
-                "        \"testApi\": \"VNF_API\"" +
+                "        \"testApi\": \"GR_API\"" +
                 "      }," +
                 "      \"project\": {" +
                 "        \"projectName\": \"Kennedy\"" +
@@ -138,7 +137,7 @@ public class PresetMSOOrchestrationRequestsGetByServiceInstanceId extends BaseMS
                 "        \"lcpCloudRegionId\":\"olson5b\"" +
                 "      }," +
                 "      \"requestParameters\":{" +
-                "        \"testApi\":\"VNF_API\"" +
+                "        \"testApi\":\"GR_API\"" +
                 "      }," +
                 "      \"platform\":{" +
                 "        \"platformName\":\"AIC\"" +
index 8855b51..66cdee3 100644 (file)
@@ -305,15 +305,19 @@ public class AsyncInstantiationBase extends BaseMsoApiTest {
         final List<String> jobIds = createBulkOfMacroInstances(presets, false, bulkSize, names);
         Assert.assertEquals(jobIds.size(),bulkSize);
 
+        waitForJobsToSuccessfullyCompleted(bulkSize, jobIds);
+        return jobIds;
+    }
+
+    public void waitForJobsToSuccessfullyCompleted(int bulkSize, List<String> jobIds) {
         assertTrue(String.format("Not all services with ids: %s are in state completed after 30 sec",
                 jobIds.stream().collect(joining(","))),
 
                 Wait.waitFor(y-> serviceListCall().getBody().stream()
                         .filter(si -> jobIds.contains(si.jobId))
-                        .filter(si -> si.jobStatus==JobStatus.COMPLETED)
+                        .filter(si -> si.jobStatus== JobStatus.COMPLETED)
                         .count() == bulkSize,
                 null, 30, 1 ));
-        return jobIds;
     }
 
     protected List<JobAuditStatus> getJobMsoAuditStatusForAlaCarte(String jobUUID, String requestId, String serviceInstanceId){
index 9f132e8..ddf0bad 100644 (file)
@@ -55,8 +55,11 @@ public enum Features implements Feature {
     FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS,
     FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND,
     FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE,
-    FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER,
     FLAG_2002_UNLIMITED_MAX,
+    FLAG_2004_INSTANTIATION_TEMPLATES_POPUP,
+    FLAG_2006_VFM_SDNC_PRELOAD_FILES,
+    FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY,
+    FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF,
     ;
 
     public boolean isActive() {
index acddc1b..0b8122c 100644 (file)
@@ -53,8 +53,4 @@ public abstract class DeployModernUIBase extends DeployDialogBase {
         GeneralUIUtils.clickOnElementByTestId(Constants.OwningEntity.PROJECT_SELECT_TEST_ID);
     }
 
-    public void clickPreviousInstantiationButton() {
-        GeneralUIUtils.clickOnElementByTestIdWithoutWait("ShowPreviousInstancesButton");
-    }
-
 }
index 92b01d1..99107ae 100644 (file)
@@ -39,7 +39,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     static final String SERVICE_NAME = "ggghhh";
     static final String SERVICE_ID = "537d3eb0-b7ab-4fe8-a438-6166ab6af49b";
     static final String VNF_ID = "0eb38f69-d96b-4d5e-b8c9-3736c292f0f7";
-    static final String DEFAULT_TEST_API_VALUE = "VNF_API";
+    static final String DEFAULT_TEST_API_VALUE = "GR_API";
     public static final String SERVICE_INSTANCE_ID = "SERVICE_INSTANCE_ID";
     public static final String A_LACARTE_FLOW_GET_ORCHESTRATION = "aLacarteFlow/get_orchestration_request_status.json";
     public static final String ORCHESTRATION_REQUEST_ID = "orchestrationRequestId";
@@ -71,7 +71,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
 
 
     @Test(dataProvider = "msoTestApiOptions")
-    private void testAddVfModule(String msoTestApiOption, String msoTestApiValue) {
+    public void testAddVfModule(String msoTestApiOption, String msoTestApiValue) {
         withMsoTestApiConfiguration(msoTestApiOption, msoTestApiValue, () -> {
             final String REQUEST_ID = "dbe54591-c8ed-46d3-abc7-d3a24873bddd";
             final String MODEL_UUID = "d205e01d-e5da-4e68-8c52-f95cb0607959";
@@ -104,7 +104,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     }
 
     @Test
-    private void testTenant() throws Exception {
+    public void testTenant() throws Exception {
         ViewEditPage viewEditPage = new ViewEditPage();
         User user = usersService.getUser("Emanuel_with_tenant");
         relogin(user.credentials);
@@ -120,7 +120,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     }
 
     @Test(dataProvider = "msoTestApiOptions")
-    private void testAddVnf(String msoTestApiOption, String msoTestApiValue) {
+    public void testAddVnf(String msoTestApiOption, String msoTestApiValue) {
         withMsoTestApiConfiguration(msoTestApiOption, msoTestApiValue, () -> {
             final String MODEL_UUID = MODEL;
             String instanceName = new VidBasePage().generateInstanceName(Constants.ViewEdit.VNF_INSTANCE_NAME_PREFIX);
@@ -145,7 +145,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     }
 
     @Test(dataProvider = "msoTestApiOptions")
-    private void requiredLineOfBussiness_confirmVnfWithNoLob(String msoTestApiOption, String msoTestApiValue) throws Exception {
+    public void requiredLineOfBussiness_confirmVnfWithNoLob(String msoTestApiOption, String msoTestApiValue) throws Exception {
         withMsoTestApiConfiguration(msoTestApiOption, msoTestApiValue, () -> {
             goToInstance();
             String instanceName = new VidBasePage().generateInstanceName(Constants.ViewEdit.VNF_INSTANCE_NAME_PREFIX);
@@ -170,7 +170,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     }
 
     @Test
-    private void emptyLobAfterReopenCreateVnfDialog() throws Exception {
+    public void emptyLobAfterReopenCreateVnfDialog() throws Exception {
         final String lobToSelect = "ONAP";
         goToInstance();
         ViewEditPage viewEditPage = new ViewEditPage();
@@ -185,7 +185,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     }
 
     @Test(dataProvider = "msoTestApiOptions")
-    private void testAddVolumeGroup(String msoTestApiOption, String msoTestApiValue) throws Exception {
+    public void testAddVolumeGroup(String msoTestApiOption, String msoTestApiValue) throws Exception {
         withMsoTestApiConfiguration(msoTestApiOption, msoTestApiValue, () -> {
             final String REQUEST_ID = "dbe54591-c8ed-46d3-abc7-d3a24873bdaa";
             final String MODEL_UUID = "13f022c4-651e-4326-b8e1-61e9a8c7a7ad";
@@ -230,8 +230,8 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
     @DataProvider
     public static Object[][] msoTestApiOptions() {
         return new Object[][]{
-                {"VNF_API (old)", DEFAULT_TEST_API_VALUE}
-                , {"GR_API (new)", "GR_API"}
+                {"GR_API (new)", DEFAULT_TEST_API_VALUE}
+                , {"VNF_API (old)", "VNF_API"}
         };
     }
 
@@ -244,7 +244,7 @@ public class ALaCarteflowTest extends CreateInstanceDialogBaseTest {
                 test.run();
             } finally {
                 // back to default
-                selectMsoTestApiOption("VNF_API (old)");
+                selectMsoTestApiOption("GR_API (new)");
             }
         }
     }
index f6b883a..84dbf11 100644 (file)
@@ -6,7 +6,6 @@ import static org.testng.Assert.assertFalse;
 import static vid.automation.test.infra.Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI;
 import static vid.automation.test.infra.Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI;
 import static vid.automation.test.infra.Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND;
-import static vid.automation.test.infra.Features.FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER;
 import static vid.automation.test.infra.Features.FLAG_5G_IN_NEW_INSTANTIATION_UI;
 import static vid.automation.test.infra.Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION;
 import static vid.automation.test.infra.Features.FLAG_SHOW_ORCHESTRATION_TYPE;
@@ -338,26 +337,6 @@ public class BrowseASDCTest extends CreateInstanceDialogBaseTest {
         return deployMacroDialog;
     }
 
-    @Test
-    @FeatureTogglingTest(FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER)
-    public void testClickPreviousInstantiationsInCreationDialog() {
-        try {
-            String serviceId = "2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd";
-            DeployModernUIMacroDialog deployMacroDialog = getDeployModernUIMacroDialog(serviceId);
-            deployMacroDialog.clickPreviousInstantiationButton();
-
-            //exit form deploy dialog
-            goOutFromIframe();
-            //go into Instantiation Status page
-            goToIframe();
-
-            InstantiationStatusPage.verifyInstantiationStatusFilterValue(serviceId);
-        }
-        finally {
-            goOutFromIframe();
-        }
-    }
-
     private BrowseASDCPage registerSimulatorAndGoToBrowseSDC() {
         SimulatorApi.registerExpectation(SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET,
                 "ecompportal_getSessionSlotCheckInterval.json",
index 351e5b0..e092ad3 100644 (file)
@@ -649,7 +649,7 @@ public class ChangeManagementTest extends VidBaseTestCase {
                                 .put("workflow", "" + workflowName + "")
                                 .put("policyYN", "Y")
                                 .put("sniroYN", "Y")
-                                .put("testApi", "VNF_API")
+                                .put("testApi", "GR_API")
                                 .put("vnfType", "vMobileDNS")
                                 .putAll(workflowParams)
                                 .build()
index df3b41d..2a12211 100644 (file)
@@ -1,20 +1,17 @@
 package vid.automation.test.test;
 
+import java.util.ArrayList;
 import org.junit.Assert;
 import org.onap.sdc.ci.tests.utilities.GeneralUIUtils;
 import org.openqa.selenium.WebElement;
 import vid.automation.test.Constants;
 import vid.automation.test.infra.Click;
 import vid.automation.test.infra.Exists;
-import vid.automation.test.infra.Get;
 import vid.automation.test.infra.SelectOption;
 import vid.automation.test.model.Service;
 import vid.automation.test.model.ServiceModel;
 import vid.automation.test.sections.ViewEditPage;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class CreateInstanceDialogBaseTest extends VidBaseTestCase {
 
     protected ViewEditPage viewEditPage= new ViewEditPage();
@@ -147,24 +144,4 @@ public class CreateInstanceDialogBaseTest extends VidBaseTestCase {
         Assert.assertTrue(field + " " + Constants.REQUIRED, byclassAndText);
     }
 
-    protected void cancelPopup() {
-        viewEditPage.clickCancelButtonByTestID();
-        GeneralUIUtils.ultimateWait();
-    }
-
-
-
-    public static void AssertUnselectedOptionInMultiselectById(String multiSelectId, String unselectedOption){
-        Click.byId(multiSelectId);
-        WebElement element = Get.byClassAndText(Constants.MULTI_SELECT_UNSELECTED_CLASS, unselectedOption);
-        Assert.assertTrue("The option "+ unselectedOption +" is already selected",element != null);
-        Click.byId(multiSelectId);
-    }
-
-    public void validateDynamicFields(List<String> dynamicFields) {
-        for (String field : dynamicFields) {
-            WebElement fieldElement = GeneralUIUtils.findByText(field);
-            Assert.assertNotNull("couldn't find dynamic field: " + field, fieldElement);
-        }
-    }
 }
diff --git a/vid-automation/src/main/java/vid/automation/test/test/ModernUITestBase.java b/vid-automation/src/main/java/vid/automation/test/test/ModernUITestBase.java
new file mode 100644 (file)
index 0000000..dd6a0f6
--- /dev/null
@@ -0,0 +1,34 @@
+package vid.automation.test.test;
+
+import static vid.automation.test.infra.ModelInfo.pasqualeVmxVpeBvService488Annotations;
+
+import com.google.common.collect.ImmutableList;
+import java.util.UUID;
+import org.jetbrains.annotations.NotNull;
+import vid.automation.test.infra.ModelInfo;
+import vid.automation.test.sections.ViewEditPage;
+
+public class ModernUITestBase extends VidBaseTestCase {
+
+    protected ViewEditPage viewEditPage = new ViewEditPage();
+
+    protected void prepareServicePreset(ModelInfo modelInfo, boolean deploy) {
+        String subscriberId = "e433710f-9217-458d-a79d-1c7aff376d89";
+
+        if (deploy) {
+            registerExpectationForServiceDeployment(
+                ImmutableList.of(
+                    modelInfo,
+                    pasqualeVmxVpeBvService488Annotations
+                ),
+                subscriberId, null);
+        } else {
+            registerExpectationForServiceBrowseAndDesign(ImmutableList.of(modelInfo), subscriberId);
+        }
+    }
+
+    @NotNull
+    protected String uuid() {
+        return UUID.randomUUID().toString();
+    }
+}
index 68a3cde..3caf59e 100644 (file)
@@ -11,6 +11,7 @@ import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOw
 import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.COMPLETE;
 import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.DEFAULT_SERVICE_INSTANCE_ID;
 import static org.testng.Assert.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertTrue;
 import static vid.automation.test.infra.Features.FLAG_1902_VNF_GROUPING;
 import static vid.automation.test.infra.Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI;
@@ -28,7 +29,6 @@ import static vid.automation.test.infra.ModelInfo.macroSriovNoDynamicFieldsEcomp
 import static vid.automation.test.infra.ModelInfo.macroSriovNoDynamicFieldsEcompNamingFalseFullModelDetailsVnfEcompNamingFalse;
 import static vid.automation.test.infra.ModelInfo.macroSriovWithDynamicFieldsEcompNamingFalsePartialModelDetailsVnfEcompNamingFalse;
 import static vid.automation.test.infra.ModelInfo.macroSriovWithDynamicFieldsEcompNamingTruePartialModelDetails;
-import static vid.automation.test.infra.ModelInfo.pasqualeVmxVpeBvService488Annotations;
 import static vid.automation.test.infra.ModelInfo.transportWithPnfsService;
 import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND;
 import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset;
@@ -48,13 +48,11 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.mutable.MutableInt;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.hamcrest.Matchers;
-import org.jetbrains.annotations.NotNull;
 import org.onap.sdc.ci.tests.datatypes.UserCredentials;
 import org.onap.sdc.ci.tests.utilities.GeneralUIUtils;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetL3NetworksByCloudRegionSpecificState;
@@ -106,7 +104,7 @@ import vid.automation.test.test.NewServiceInstanceTest.ServiceData.IS_GENERATED_
 import vid.automation.test.utils.ReadFile;
 
 @FeatureTogglingTest(FLAG_ENABLE_WEBPACK_MODERN_UI)
-public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest {
+public class NewServiceInstanceTest extends ModernUITestBase {
 
     public static final String COMPLETED = "COMPLETED";
     private static final String IN_PROGRESS = "IN_PROGRESS";
@@ -1186,12 +1184,15 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest {
 
         browseASDCPage.selectTenant("092eb9e8e4b7412e8787dd091bc58e86");
 
+
         assertSetButtonDisabled(VNF_SET_BUTTON_TEST_ID);
 
         if(isNetwork){
             browseASDCPage.selectPlatform("platform");
         }else {
             SelectOption.selectOptionsFromMultiselectById("multi-selectPlatform", ImmutableList.of("platform"));
+            SelectOption.byTestIdAndVisibleText("TYLER SILVIA", Constants.ViewEdit.PRODUCT_FAMILY_SELECT_TESTS_ID);
+            browseASDCPage.selectProductFamily("e433710f-9217-458d-a79d-1c7aff376d89");
         }
 
         browseASDCPage.selectLineOfBusiness("ONAP");
@@ -1384,12 +1385,13 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest {
         }
     }
 
-    @NotNull
-    private String uuid() {
-        return UUID.randomUUID().toString();
+    public void validateDynamicFields(List<String> dynamicFields) {
+        for (String field : dynamicFields) {
+            WebElement fieldElement = GeneralUIUtils.findByText(field);
+            assertNotNull("couldn't find dynamic field: " + field, fieldElement);
+        }
     }
 
-
     private void assertNotificationAreaVisibilityBehaviourAndSetBulkSize(int size) {
         WebElement webElement = Get.byId("notification-area");
         Assert.assertNull(webElement, "notification area should be invisible if only 1 qty.");
@@ -1400,22 +1402,6 @@ public class NewServiceInstanceTest extends CreateInstanceDialogBaseTest {
         Assert.assertNotNull(webElement, "notification area should be visible if more then 1 qty.");
     }
 
-    //@Step("prepare service preset")
-    private void prepareServicePreset(ModelInfo modelInfo, boolean deploy) {
-        String subscriberId = "e433710f-9217-458d-a79d-1c7aff376d89";
-
-        if (deploy) {
-            registerExpectationForServiceDeployment(
-                ImmutableList.of(
-                    modelInfo,
-                    pasqualeVmxVpeBvService488Annotations
-                ),
-                subscriberId, null);
-        } else {
-            registerExpectationForServiceBrowseAndDesign(ImmutableList.of(modelInfo), subscriberId);
-        }
-    }
-
     static class ServiceData {
 
         ServiceData(String modelUuid, List<String> dynamicFields, IS_GENERATED_NAMING isServiceGeneratedNaming,
index b1d31f8..abeffca 100644 (file)
@@ -1,7 +1,10 @@
 package vid.automation.test.test;
 
-import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
 import org.onap.sdc.ci.tests.utilities.GeneralUIUtils;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import vid.automation.test.Constants;
@@ -12,9 +15,6 @@ import vid.automation.test.sections.SideMenu;
 import vid.automation.test.services.BulkRegistration;
 import vid.automation.test.services.SimulatorApi;
 
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
 public class SearchExistingInstanceTest extends VidBaseTestCase {
 
     public static final String serviceIdOeWirelineProjectX1 = "7e4f8130-5dee-47c4-8770-1abc5f5ded83";
@@ -27,7 +27,7 @@ public class SearchExistingInstanceTest extends VidBaseTestCase {
     }
 
     @Test
-    private void testSearchExistingInstanceByOwningEntitySingleValue() {
+    public void testSearchExistingInstanceByOwningEntitySingleValue() {
         SearchExistingPage searchExistingPage = new SearchExistingPage();
         SideMenu.navigateToSearchExistingPage();
         searchExistingPage.searchByOwningEntity("Melissa");
diff --git a/vid-automation/src/main/java/vid/automation/test/test/TemplateInstantiationTest.java b/vid-automation/src/main/java/vid/automation/test/test/TemplateInstantiationTest.java
new file mode 100644 (file)
index 0000000..f2b0fb1
--- /dev/null
@@ -0,0 +1,143 @@
+package vid.automation.test.test;
+
+import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId.PRESET_SOME_LEGACY_REGION_TO_ATT_AIC;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet.COMPLETE;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys.SERVICE_NAME;
+import static org.onap.vid.api.TestUtils.generateRandomAlphaNumeric;
+import static vid.automation.test.Constants.BrowseASDC.NewServicePopup.SET_BUTTON;
+import static vid.automation.test.Constants.DrawingBoard.CONTEXT_MENU_BUTTON_HEADER;
+import static vid.automation.test.Constants.DrawingBoard.CONTEXT_MENU_HEADER_EDIT_ITEM;
+import static vid.automation.test.Constants.DrawingBoard.DEPLOY_BUTTON;
+import static vid.automation.test.infra.Features.FLAG_2004_INSTANTIATION_TEMPLATES_POPUP;
+import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND;
+import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET;
+import static vid.automation.test.services.SimulatorApi.registerExpectationFromPresets;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import org.onap.sdc.ci.tests.datatypes.UserCredentials;
+import org.onap.sdc.ci.tests.utilities.GeneralUIUtils;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceAlacarte;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys;
+import org.onap.vid.api.AsyncInstantiationBase;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import vid.automation.test.infra.Click;
+import vid.automation.test.infra.FeatureTogglingTest;
+import vid.automation.test.infra.Get;
+import vid.automation.test.infra.Input;
+import vid.automation.test.infra.ModelInfo;
+import vid.automation.test.sections.DrawingBoardPage;
+import vid.automation.test.sections.SideMenu;
+import vid.automation.test.sections.VidBasePage;
+import vid.automation.test.services.AsyncJobsService;
+
+public class TemplateInstantiationTest extends ModernUITestBase {
+
+    private AsyncInstantiationBase asyncInstantiationBase;
+
+    @BeforeClass
+    protected void setUp() {
+        AsyncJobsService asyncJobsService = new AsyncJobsService();
+        asyncJobsService.dropAllAsyncJobs();
+        asyncInstantiationBase = new AsyncInstantiationBase();
+        asyncInstantiationBase.init();
+        UserCredentials userCredentials = getUserCredentials();
+        //login for API test (needed besides selenium test via browser)
+        asyncInstantiationBase.login(userCredentials);
+    }
+
+    @AfterClass
+    protected void tearDown() {
+        AsyncJobsService asyncJobsService = new AsyncJobsService();
+        asyncJobsService.muteAllAsyncJobs();
+    }
+
+    /*
+        In this test we create an simple aLaCarte service via api,
+        Then browse SDC -> search for same model uuid -> deploy ->
+        template popup is opened -> select the service -> click load template ->
+        drawing board is opened -> edit service instance name -> deploy ->
+        instantiation status is opened -> wait for service to completed.
+     */
+    @FeatureTogglingTest(FLAG_2004_INSTANTIATION_TEMPLATES_POPUP)
+    @Test
+    public void instantiateALaCarteServiceFromTemplateTest() {
+
+        final ModelInfo modelInfo = ModelInfo.aLaCarteServiceCreationNewUI;
+        String templateInstanceName = "template"+generateRandomAlphaNumeric(10);
+        String requestorID = getUserCredentials().getUserId();
+        String serviceRequestId = uuid();
+        String serviceInstanceId = uuid();
+
+        //prepare presets for first instantiation (template), and rest of scenario till deploy
+        prepareServicePreset(modelInfo, true);
+        registerExpectationFromPresets(
+            ImmutableList.of(
+                new PresetMSOCreateServiceInstanceAlacarte(
+                    ImmutableMap.of(Keys.SERVICE_NAME, templateInstanceName),
+                    serviceRequestId, serviceInstanceId,
+                    requestorID, modelInfo),
+                PRESET_SOME_LEGACY_REGION_TO_ATT_AIC,
+                new PresetMSOOrchestrationRequestGet(COMPLETE, serviceRequestId)
+            ),
+            APPEND
+        );
+
+        //create service instance via API
+        final List<String> jobsIds = asyncInstantiationBase.createBulkOfInstances(false, 1,
+            ImmutableMap.of(SERVICE_NAME, templateInstanceName), "asyncInstantiation/vidRequestCreateALaCarteForTemplate.json");
+        asyncInstantiationBase.waitForJobsToSuccessfullyCompleted(1, jobsIds);
+
+        String newInstanceName = "template"+generateRandomAlphaNumeric(10);
+        String serviceRequestId2 = uuid();
+        String serviceInstanceId2 = uuid();
+
+        //load template and and edit service instance name
+        browseSdcAndClickDeploy(modelInfo);
+        selectTemplateByNameAndLoadTemplate(templateInstanceName);
+        VidBasePage.goToIframe();
+        editServiceInstanceName(newInstanceName);
+
+        //prepare presets for second service instance deploy
+        registerExpectationFromPresets(
+            ImmutableList.of(
+                new PresetMSOCreateServiceInstanceAlacarte(
+                    ImmutableMap.of(Keys.SERVICE_NAME, newInstanceName),
+                    serviceRequestId2, serviceInstanceId2,
+                    requestorID, modelInfo),
+                PRESET_SOME_LEGACY_REGION_TO_ATT_AIC,
+                new PresetMSOOrchestrationRequestGet(COMPLETE, serviceRequestId2)
+            ),
+            CLEAR_THEN_SET
+        );
+
+        //deploy the service and wait for completion
+        Click.byTestId(DEPLOY_BUTTON);
+        VidBasePage.goToIframe();
+        new DrawingBoardPage().verifyServiceCompletedOnTime(newInstanceName, "service deployed from template");
+    }
+
+    private void browseSdcAndClickDeploy(ModelInfo modelInfo) {
+        SideMenu.navigateToBrowseASDCPage();
+        GeneralUIUtils.ultimateWait();
+        loadTemplatesPopupOnBrowseASDCPage(modelInfo.modelVersionId);
+    }
+
+    private void selectTemplateByNameAndLoadTemplate(String templateInstanceName) {
+        Click.byText(templateInstanceName);
+        Click.byTestId("LoadTemplateButton");
+    }
+
+    private void editServiceInstanceName(String newInstanceName) {
+        GeneralUIUtils.getClickableButtonBy(Get.getXpathForDataTestId(CONTEXT_MENU_BUTTON_HEADER), 60).click();
+        Click.byTestId(CONTEXT_MENU_HEADER_EDIT_ITEM);
+        GeneralUIUtils.ultimateWait();
+        Input.replaceText(newInstanceName, "instanceName");
+        Click.byTestId(SET_BUTTON);
+    }
+
+}
index c2733f0..8421427 100644 (file)
@@ -113,7 +113,7 @@ public class VidBaseTestCase extends SetupCDTest{
         } catch (URISyntaxException e) {
             throw new RuntimeException(e);
         }
-        this.uri = new JerseyUriBuilder().host(envUrI.getHost()).port(envUrI.getPort()).scheme("http").path("vid").build();
+        this.uri = new JerseyUriBuilder().host(envUrI.getHost()).port(envUrI.getPort()).scheme(envUrI.getScheme()).path("vid").build();
     }
 
     public void login() {
@@ -523,13 +523,21 @@ public class VidBaseTestCase extends SetupCDTest{
         loadServicePopupOnBrowseASDCPage(modelVersionId);
     }
 
-    protected void loadServicePopupOnBrowseASDCPage(String modelVersionId ) {
+    protected void loadServicePopupOnBrowseASDCPage(String modelVersionId) {
+        loadServicePopupOnBrowseASDCPage(modelVersionId, "Model version");
+    }
+
+    protected void loadTemplatesPopupOnBrowseASDCPage (String modelVersionId) {
+        loadServicePopupOnBrowseASDCPage(modelVersionId, "Templates");
+    }
+
+    protected void loadServicePopupOnBrowseASDCPage(String modelVersionId, String expectedText) {
         DeployModernUIMacroDialog deployMacroDialog = new DeployModernUIMacroDialog();
         VidBasePage.goOutFromIframe();
         deployMacroDialog.clickDeployServiceButtonByServiceUUID(modelVersionId);
         deployMacroDialog.goToIframe();
         GeneralUIUtils.ultimateWait();
-        Wait.byText("Model version");
+        Wait.byText(expectedText);
     }
 
     public void assertSetButtonDisabled(String buttonTestId) {
index cbc28d0..94af659 100644 (file)
@@ -4,8 +4,8 @@ import static org.apache.logging.log4j.core.util.Assert.isNonEmpty;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.matchesPattern;
 import static org.hamcrest.collection.IsEmptyCollection.empty;
-import static org.testng.AssertJUnit.assertEquals;
 import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND;
 
 import com.google.common.collect.ImmutableMap;
@@ -14,6 +14,7 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -55,7 +56,7 @@ public class ViewEditServiceInstanceTest extends VidBaseTestCase {
     private final String crNetworkText ="NETWORK INSTANCE GROUP: l3network-id-rs804s | ROLE: RosemaProtectedOam.OAM | TYPE: Tenant_Layer_3 | # OF NETWORKS: 3";
     private final String crCollectionText ="COLLECTION: collection-name | TYPE: L3-NETWORK";
     private final String crInfoText = "\"requestState\": \"COMPLETE\"";
-    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
+    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.US);
     static final String LCP_REGION = "hvf6";
     static final String CLOUD_OWNER = "AIC";
     static final String TENANT = "bae71557c5bb4d5aac6743a4e5f1d054";
@@ -284,6 +285,7 @@ public class ViewEditServiceInstanceTest extends VidBaseTestCase {
         viewEditPage.clickCloseButton();
     }
 
+    //this test works only if your browser run at UTC timezone
     @Test
     public void testTimestampOnDeactivateAndInfoServiceInstance() throws ParseException {
         SimulatorApi.clearAll();
@@ -296,7 +298,7 @@ public class ViewEditServiceInstanceTest extends VidBaseTestCase {
         goToExistingInstanceById(serviceInstanceId);
         Click.byClass("service-info");
         GeneralUIUtils.ultimateWait();
-        assertEquals("Timestamp isn't the finished time", getTimeatampValue(Constants.ViewEdit.DETAILS_LOG), "Tue, 24 Oct 2017 02:28:39");
+        assertThat("Timestamp isn't the finished time", getTimeatampValue(Constants.ViewEdit.DETAILS_LOG), matchesPattern("Mon, 23 Oct 2017 [0-9]{1,2}:28:39")); //timezone insensitive
         viewEditPage.clickCloseButton();
         viewEditPage.clickDeactivateButton();
         GeneralUIUtils.ultimateWait();
index d8aebc7..222f895 100644 (file)
         "bulkSize": "3",
         "aicZoneName": "NFTJSSSS-NFT1",
         "owningEntityName": "WayneHolland",
-        "testApi": "VNF_API",
+        "testApi": "GR_API",
         "tenantName": "AIN Web Tool-15-D-testalexandria",
         "modelInfo": {
           "modelInvariantId": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
index 71ba536..0496266 100644 (file)
@@ -20,7 +20,7 @@
   "tenantId" : "c85f0e80-0636-44a4-8cb2-4ec00d056e79",
   "tenantName" : "Hedvika Wendelin",
   "bulkSize": "1",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true
 }
 
diff --git a/vid-automation/src/main/resources/asyncInstantiation/vidRequestCreateALaCarteForTemplate.json b/vid-automation/src/main/resources/asyncInstantiation/vidRequestCreateALaCarteForTemplate.json
new file mode 100644 (file)
index 0000000..3abb41f
--- /dev/null
@@ -0,0 +1,57 @@
+{
+  "action": "Create",
+  "isDirty": true,
+  "vnfs": {},
+  "vrfs": {},
+  "instanceParams": [{}
+  ],
+  "validationCounter": 0,
+  "existingNames": {
+    "alacartewithvnfzvcjg": ""
+  },
+  "existingVNFCounterMap": {
+    "e9ed1da0-c078-426a-8e84-6f4e85eace59": 0
+  },
+  "existingVRFCounterMap": {},
+  "existingVnfGroupCounterMap": {},
+  "existingNetworksCounterMap": {},
+  "networks": {},
+  "vnfGroups": {},
+  "bulkSize": 1,
+  "instanceName": "SERVICE_NAME",
+  "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89",
+  "subscriptionServiceType": "TYLER SILVIA",
+  "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc",
+  "projectName": "WATKINS",
+  "rollbackOnFailure": true,
+  "aicZoneName": null,
+  "owningEntityName": "WayneHolland",
+  "testApi": "GR_API",
+  "tenantName": null,
+  "modelInfo": {
+    "modelInvariantId": "d1068db8-b933-4919-8972-8bc1aed366c8",
+    "modelVersionId": "f3862254-8df2-4a0a-8137-0a9fe985860c",
+    "modelName": "vOCG_1804_SVC",
+    "modelVersion": "1.0",
+    "uuid": "f3862254-8df2-4a0a-8137-0a9fe985860c",
+    "modelUniqueId": "f3862254-8df2-4a0a-8137-0a9fe985860c"
+  },
+  "isALaCarte": true,
+  "name": "vOCG_1804_SVC",
+  "version": "1.0",
+  "description": "updated HEAT",
+  "category": "Emanuel",
+  "uuid": "f3862254-8df2-4a0a-8137-0a9fe985860c",
+  "invariantUuid": "d1068db8-b933-4919-8972-8bc1aed366c8",
+  "serviceType": "",
+  "serviceRole": "",
+  "vidNotions": {
+    "instantiationUI": "anyAlacarteWhichNotExcluded",
+    "modelCategory": "other",
+    "viewEditUI": "legacy",
+    "instantiationType": "ALaCarte"
+  },
+  "isEcompGeneratedNaming": true,
+  "isMultiStepDesign": false,
+  "subscriberName": "SILVIA ROBBINS"
+}
\ No newline at end of file
index c6529c8..b145f3e 100644 (file)
@@ -41,7 +41,7 @@
   "tenantId" : "c85f0e80-0636-44a4-8cb2-4ec00d056e79",
   "tenantName" : "Hedvika Wendelin",
   "bulkSize": "BULK_SIZE",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true
 }
 
index 3e31a39..a6b8088 100644 (file)
@@ -22,7 +22,7 @@
           "modelCustomizationName": "AIC30_CONTRAIL_BASIC 0"
         },
         "requestParameters": {
-          "testApi": "VNF_API",
+          "testApi": "GR_API",
           "userParams": []
         },
         "cloudConfiguration": {
index 5cf1c34..d6c4ec3 100644 (file)
@@ -21,7 +21,7 @@
           "userParams": [],
           "subscriptionServiceType": "TYLER SILVIA",
           "aLaCarte": true,
-          "testApi": "VNF_API"
+          "testApi": "GR_API"
         },
         "subscriberInfo": {
           "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89",
index 1106697..e45de76 100644 (file)
@@ -13,7 +13,7 @@
         {
           "request": {
             "requestId": "678cc766-b673-4a50-b9c5-471f68914590",
-            "startTime": "Mon, 23 Oct 2017 23:28:39 GMT",
+            "startTime": "Mon, 23 Oct 2017 15:28:39 GMT",
             "requestScope": "service",
             "requestType": "createInstance",
             "instanceReferences": {
@@ -24,7 +24,7 @@
               "requestState": "COMPLETE",
               "statusMessage": "Service Instance was created successfully.",
               "percentProgress": 100,
-              "finishTime": "Mon, 23 Oct 2017 23:28:39 GMT"
+              "finishTime": "Mon, 23 Oct 2017 15:28:39 GMT"
             }
           }
         }
index c7d245f..68ad69c 100644 (file)
@@ -1,4 +1,10 @@
-{
-  "param": "ABCD",
-  "vnf_instance_name": "sample"
-}
\ No newline at end of file
+[
+  {
+  "name": "param",
+  "value": "ABCD"
+  },
+  {
+    "name": "vnf_instance_name",
+    "value": "sample"
+  }
+]
index 05d73a6..54300c2 100644 (file)
@@ -2,6 +2,7 @@ package org.onap.vid.api;
 
 import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIStandardQueryGet.defaultPlacement;
 import static org.onap.simulator.presetGenerator.presets.aai.PresetAAIStandardQueryGet.ofL3Network;
@@ -13,12 +14,15 @@ import static org.onap.simulator.presetGenerator.presets.ecompportal_att.EcompPo
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.AssertJUnit.assertEquals;
+import static vid.automation.test.Constants.RegisterToSimulator.SearchForServiceInstance.GET_SUBSCRIBERS_FOR_CUSTOMER_CRAIG_ROBERTS;
 import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.APPEND;
 import static vid.automation.test.services.SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET;
 import static vid.automation.test.services.SimulatorApi.registerExpectationFromPresets;
 import static vid.automation.test.utils.TestHelper.GET_SERVICE_MODELS_BY_DISTRIBUTION_STATUS;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
@@ -43,6 +47,7 @@ import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetInstanceGroups
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetInstanceGroupsByCloudRegionRequiredMissing;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetL3NetworksByCloudRegion;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetL3NetworksByCloudRegionSpecificState;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetModelsByOwningEntity;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkCollectionDetails;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkCollectionDetailsInvalidRequest;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetNetworkCollectionDetailsRequiredMissing;
@@ -101,6 +106,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
             "  }, {\n" +
@@ -115,6 +121,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_ERROR\",\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
             "  }, {\n" +
@@ -128,6 +135,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -143,6 +151,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
             "  }, {\n" +
@@ -157,6 +166,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
             "  }, {\n" +
@@ -170,6 +180,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -184,6 +195,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -198,6 +210,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -212,6 +225,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -226,6 +240,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -240,6 +255,7 @@ public class AaiApiTest extends BaseApiAaiTest {
             "    \"lastUpdaterUserId\": null,\n" +
             "    \"lastUpdaterFullName\": null,\n" +
             "    \"orchestrationType\": null,\n" +
+            "    \"isInstantiationTemplateExists\": false,\n" +
             "    \"distributionStatus\": \"DISTRIBUTION_COMPLETE_OK\",\n" +
             "    \"artifacts\": null,\n" +
             "    \"resources\": null\n" +
@@ -887,6 +903,49 @@ public class AaiApiTest extends BaseApiAaiTest {
         assertThat(response.getBody(), jsonEquals(getResourceAsString(AAI_VNFS_FOR_CHANGE_MANAGEMENT_JSON_BY_PARAMS)));
     }
 
+    @Test
+    public void searchServiceInstancesBySubscriber_serviceInstanceOfAnotherSubscriber_authIsFollowingFeatureToggle() {
+        String craigRobertsSubscriberId = "31739f3e-526b-11e6-beb8-9e71128cae77";
+        String aServiceOwningEntityId = "f160c875-ddd1-4ef5-84d8-d098784daa3a";
+        String currentUserAuthorizedOwningEntityId = "SILVIA ROBBINS"; // this will need to change with translateOwningEntityNameToOwningEntityId
+
+        SimulatorApi.registerExpectation(GET_SUBSCRIBERS_FOR_CUSTOMER_CRAIG_ROBERTS,
+            ImmutableMap.of(aServiceOwningEntityId, currentUserAuthorizedOwningEntityId), CLEAR_THEN_SET);
+
+        searchServicesAndAssertIsPermitted("subscriberId=" + craigRobertsSubscriberId, "4ea864f2-b946-473a-b51c-51a7c10b8391");
+    }
+
+    @Test
+    public void searchServiceInstancesByOwningEntity_serviceInstanceOfAnotherSubscriber_authIsFollowingFeatureToggle() {
+        String owningEntityName = "someOwning";
+        String owningEntityId = "SILVIA ROBBINS"; // this will need to change with translateOwningEntityNameToOwningEntityId
+
+        SimulatorApi.registerExpectationFromPreset(new PresetAAIGetModelsByOwningEntity(owningEntityName, owningEntityId, "fakeSubscriberId"), CLEAR_THEN_SET);
+
+        searchServicesAndAssertIsPermitted("owningEntity=" + owningEntityName, "af9d52f9-13b2-4657-a198-463677f82dc0");
+    }
+
+    private void searchServicesAndAssertIsPermitted(String queryParams, String aServiceInstanceId) {
+        boolean expectedPermission = Features.FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY.isActive();
+
+        SimulatorApi.registerExpectationFromPreset(new PresetAAIGetSubscribersGet(), APPEND);
+
+        JsonNode serviceInstancesResult = restTemplate
+            .getForObject(uri + "/search_service_instances?" + queryParams, JsonNode.class);
+
+        assertThat(serviceInstancesResult.path("service-instances").isArray(), is(true));
+
+        ArrayNode servicesArray = ((ArrayNode) serviceInstancesResult.path("service-instances"));
+
+        JsonNode aServiceResult = Streams.fromIterator(servicesArray.iterator())
+            .filter(it -> it.path("serviceInstanceId").asText().equals(aServiceInstanceId))
+            .findAny()
+            .orElseThrow(() -> new AssertionError("could not find serviceInstanceId=" + aServiceInstanceId));
+
+        assertThat(aServiceResult.toString(),
+            aServiceResult.path("isPermitted").booleanValue(), is(expectedPermission));
+    }
+
     private void assertResponse(Object expected, String response) {
         assertResponse(Configuration.empty(), expected, response);
     }
index 9651002..962a786 100644 (file)
@@ -18,7 +18,6 @@ import static org.hamcrest.Matchers.matchesPattern;
 import static vid.automation.test.services.SimulatorApi.retrieveRecordedRequests;
 
 import com.fasterxml.jackson.databind.JsonNode;
-
 import java.lang.reflect.Method;
 import java.net.URI;
 import java.util.ArrayList;
@@ -28,12 +27,15 @@ import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.jetbrains.annotations.NotNull;
 import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
 import org.onap.vid.api.BaseApiTest;
+import org.springframework.web.client.RestClientException;
 import org.springframework.web.client.RestTemplate;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -234,12 +236,29 @@ public class LoggerFormatTest extends BaseApiTest {
     }
 
     private JsonNode getCheckerResults (String logtype, String logLines){
+
+        final int MAX_RETRIES = 3;
+
         Map<String, String> params = new HashMap<>();
         params.put("format", "raw");
         params.put("type", logtype);
         params.put("component", "vid");
         params.put("data", logLines);
 
-        return restTemplate.postForObject(logChecker, params, JsonNode.class);
+        for (int i=0; i< MAX_RETRIES; i++) {
+            try {
+                return restTemplate.postForObject(logChecker, params, JsonNode.class);
+            } catch (RestClientException exception) { //retry for cases that logchecker is not available immediately
+                logger.error("Failed to call to logChecker try: " + i, exception);
+                if (i<(MAX_RETRIES-1)) { //no need to sleep on last retry
+                    try {
+                        Thread.sleep((new Random().nextInt(2000) + 1000)); //random sleep between 1-3 seconds
+                    } catch (InterruptedException e) {
+                        ExceptionUtils.rethrow(e);
+                    }
+                }
+            }
+        }
+        throw new AssertionError("failed to call to logChecker after max retries: "+MAX_RETRIES);
     }
 }
index b7c6dc2..7dfe064 100644 (file)
   "instanceName": "SERVICE_INSTANCE_NAME",
   "owningEntityName": null,
   "rollbackOnFailure": false,
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true,
   "vidNotions": {
     "instantiationUI": "serviceWithVnfGrouping",
index bb0334b..478c32a 100644 (file)
@@ -64,7 +64,7 @@
   "subscriberName": "SILVIA ROBBINS",
   "owningEntityName": "WayneHolland",
   "rollbackOnFailure": true,
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true,
   "isDirty":true,
   "action": "Create"
index cabdbca..aeaf6b6 100644 (file)
@@ -43,7 +43,7 @@
   "subscriptionServiceType": "service-instance-type",
   "tenantId": null,
   "tenantName": null,
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "validationCounter": 0,
   "vnfGroups": {
     "VNF_GROUP1_INSTANCE_ID": {
diff --git a/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-lcp-tenant.json b/vid-automation/src/test/resources/a-la-carte/redux-a-la-carte-no-lcp-tenant.json
new file mode 100644 (file)
index 0000000..a38469e
--- /dev/null
@@ -0,0 +1,84 @@
+{
+  "vnfs": {
+    "2017-488_PASQUALE-vPE 0": {
+      "action": "Create",
+      "rollbackOnFailure": "true",
+      "vfModules": {
+        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
+          "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
+            "instanceName": "mimazepubi",
+            "rollbackOnFailure": "false",
+            "sdncPreLoad": false,
+            "instanceParams": [
+              {}
+            ],
+            "modelInfo": {
+              "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091",
+              "modelVersionId": "f8360508-3f17-4414-a2ed-6bc71161e8db",
+              "modelName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
+              "modelVersion": "5",
+              "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
+              "modelUniqueId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
+              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
+              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db"
+            },
+            "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
+            "isMissingData": false
+          }
+        },
+        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
+          "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
+            "instanceName": "puwesovabe",
+            "volumeGroupName": "puwesovabe_vol",
+            "rollbackOnFailure": "true",
+            "sdncPreLoad": true,
+            "instanceParams": [
+              {
+                "pasqualevpe0_bandwidth": "10",
+                "2017488_pasqualevpe0_vnf_instance_name": "mtnj309me6",
+                "2017488_pasqualevpe0_vnf_config_template_version": "17.2",
+                "2017488_pasqualevpe0_AIC_CLLI": "ATLMY8GA",
+                "pasqualevpe0_bandwidth_units": "Gbps"
+              }
+            ],
+            "modelInfo": {
+              "modelInvariantId": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
+              "modelVersionId": "25284168-24bb-4698-8cb4-3f509146eca5",
+              "modelName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
+              "modelVersion": "6",
+              "modelCustomizationId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
+              "modelUniqueId": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
+              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
+              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5"
+            },
+            "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
+            "isMissingData": false
+          }
+        },
+        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
+          "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
+            "instanceName": "bnmgtrx",
+            "volumeGroupName": "",
+            "rollbackOnFailure": "false",
+            "sdncPreLoad": false,
+            "instanceParams": [
+              {}
+            ],
+            "modelInfo": {
+              "modelInvariantId": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
+              "modelVersionId": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
+              "modelName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
+              "modelVersion": "6",
+              "modelCustomizationId": "3cd946bb-50e0-40d8-96d3-c9023520b557",
+              "modelUniqueId": "3cd946bb-50e0-40d8-96d3-c9023520b557",
+              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
+              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a"
+            },
+            "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
+            "isMissingData": false
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
index 7cf11c8..5f789e0 100644 (file)
@@ -23,8 +23,7 @@
       },
       "type": "VL",
       "instanceName" : "NetInstance",
-      "modelCustomizationName": "ExtVL 0",
-      "isFailed": true
+      "modelCustomizationName": "ExtVL 0"
     }
   },
   "vnfs": {
index d5b282e..aa1945f 100644 (file)
@@ -57,7 +57,7 @@
   "bulkSize": 1,
   "rollbackOnFailure": "false",
   "isALaCarte": true,
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "instanceId": "INSTANCE_ID",
   "action": "None",
   "trackById": "TRACK_BY_ID",
index 28761f3..0d840da 100644 (file)
@@ -33,7 +33,7 @@
   "subscriptionServiceType": "TYLER SILVIA",
   "tenantId": "c85f0e80-0636-44a4-8cb2-4ec00d056e79",
   "tenantName": "Hedvika Wendelin",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "trackById": "TRACK_BY_ID",
   "vnfGroups": {
   },
index 01702b3..a62360c 100644 (file)
@@ -13,7 +13,7 @@
   "existingNetworksCounterMap": {
   },
   "existingVNFCounterMap": {
-    "024a417d-ca46-40bf-95ce-809c6a269011": 1
+    "024a417d-ca46-40bf-95ce-809c6a269011": 2
   },
   "existingVnfGroupCounterMap": {
   },
               }
             ],
             "isMissingData": false,
-            "lcpCloudRegionId": "hvf6",
             "modelInfo": {
               "modelCustomizationId": "4d0818cf-eaa9-4a3f-89c2-639953089e14",
               "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0",
             },
             "rollbackOnFailure": true,
             "sdncPreLoad": null,
-            "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
             "uuid": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88"
           }
         }
       }
+    },
+    "vProbe_NC_VNF 0_1": {
+      "modelInfo": {
+        "modelCustomizationName": "vProbe_NC_VNF 0",
+        "modelCustomizationId": "024a417d-ca46-40bf-95ce-809c6a269011",
+        "modelInvariantId": "a6a96924-b9c5-4c85-ae18-cbfca848095e",
+        "modelVersionId": "21ae311e-432f-4c54-b855-446d0b8ded72",
+        "modelName": "vProbe_NC_VNF",
+        "modelType": "vnf",
+        "modelVersion": "1.0"
+      },
+      "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89",
+      "instanceName": "hvf6arlba008",
+      "vnfStoreKey": "vProbe_NC_VNF 0_1",
+      "action": "Create",
+      "platformName": "xxx1",
+      "lcpCloudRegionId": "hvf6",
+      "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
+      "instanceParams": [
+        {}
+      ],
+      "rollbackOnFailure": true,
+      "instanceId": null,
+      "vfModules": {
+        "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0": {
+          "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0ahubg": {
+            "modelInfo": {
+              "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0",
+              "modelCustomizationId": "4d0818cf-eaa9-4a3f-89c2-639953089e14",
+              "modelInvariantId": "29b6fa3c-aeb3-4103-b3f7-6f98e097b005",
+              "modelVersionId": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88",
+              "modelName": "VprobeNcVnf..FE_base_module..module-0",
+              "modelType": "vfModule",
+              "modelVersion": "1"
+            },
+            "instanceName": "hvf6arlba007_lba_Base_02",
+            "action": "Create",
+            "lcpCloudRegionId": "hvf6",
+            "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
+            "instanceParams": [
+              {}
+            ],
+            "rollbackOnFailure": true,
+            "trackById": "ea2879a6-10bc-4697-90d7-7bc3e71da0fd",
+            "isFailed": false
+          }
+        },
+        "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": {
+          "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1yprvi": {
+            "modelInfo": {
+              "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1",
+              "modelCustomizationId": "9b99d340-a80b-45ef-9ff1-993fa3e4c001",
+              "modelInvariantId": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05",
+              "modelVersionId": "c09e4530-8fd8-418f-9483-2f57ce927b05",
+              "modelName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1",
+              "modelType": "vfModule",
+              "modelVersion": "1"
+            },
+            "instanceName": "my_hvf6arlba007_lba_dj_02",
+            "action": "Create",
+            "lcpCloudRegionId": "hvf6",
+            "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
+            "instanceParams": [
+              {}
+            ],
+            "rollbackOnFailure": true,
+            "trackById": "b134410e-3bc0-478e-883e-1b6bdf8a28df",
+            "isFailed": false,
+            "volumeGroupName": "my_special_hvf6arlba007_lba_dj_01_vol",
+            "sdncPreLoad": true
+          }
+        }
+      },
+      "trackById": "1d2848a0-3573-4d29-b3dd-60bb263260ea",
+      "isFailed": false,
+      "statusMessage": null,
+      "position": null,
+      "lineOfBusiness": "zzz1"
     }
   },
   "vrfs": {
index 5a327fd..56ba46b 100644 (file)
@@ -25,7 +25,7 @@
   "testApi": "GR_API",
   "trackById": "36601560-f8e3-4020-bdef-3e4709c51e84",
   "existingVNFCounterMap": {
-    "024a417d-ca46-40bf-95ce-809c6a269011": 1
+    "024a417d-ca46-40bf-95ce-809c6a269011": 2
   },
   "existingVRFCounterMap": {},
   "existingVnfGroupCounterMap": {},
             },
             "instanceName": "hvf6arlba007_lba_Base_01",
             "action": "Create",
+            "instanceParams": [
+              {}
+            ],
+            "rollbackOnFailure": true,
+            "trackById": "ea2879a6-10bc-4697-90d7-7bc3e71da0fd",
+            "isFailed": false
+          }
+        },
+        "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1": {
+          "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1yprvi": {
+            "modelInfo": {
+              "modelCustomizationName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1",
+              "modelCustomizationId": "9b99d340-a80b-45ef-9ff1-993fa3e4c001",
+              "modelInvariantId": "1bcc4824-6c1a-4b51-af7c-076b7fc14d05",
+              "modelVersionId": "c09e4530-8fd8-418f-9483-2f57ce927b05",
+              "modelName": "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1",
+              "modelType": "vfModule",
+              "modelVersion": "1"
+            },
+            "instanceName": "my_hvf6arlba007_lba_dj_01",
+            "action": "Create",
+            "lcpCloudRegionId": "hvf6",
+            "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
+            "instanceParams": [
+              {}
+            ],
+            "rollbackOnFailure": true,
+            "trackById": "b134410e-3bc0-478e-883e-1b6bdf8a28df",
+            "isFailed": false,
+            "volumeGroupName": "my_special_hvf6arlba007_lba_dj_01_vol",
+            "sdncPreLoad": true
+          }
+        }
+      },
+      "trackById": "1d2848a0-3573-4d29-b3dd-60bb263260ea",
+      "isFailed": false,
+      "statusMessage": null,
+      "position": null,
+      "lineOfBusiness": "zzz1"
+    },
+    "vProbe_NC_VNF 0_1": {
+      "modelInfo": {
+        "modelCustomizationName": "vProbe_NC_VNF 0",
+        "modelCustomizationId": "024a417d-ca46-40bf-95ce-809c6a269011",
+        "modelInvariantId": "a6a96924-b9c5-4c85-ae18-cbfca848095e",
+        "modelVersionId": "21ae311e-432f-4c54-b855-446d0b8ded72",
+        "modelName": "vProbe_NC_VNF",
+        "modelType": "vnf",
+        "modelVersion": "1.0"
+      },
+      "productFamilyId": "e433710f-9217-458d-a79d-1c7aff376d89",
+      "instanceName": "hvf6arlba008",
+      "action": "Create",
+      "platformName": "xxx1",
+      "lcpCloudRegionId": "hvf6",
+      "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
+      "instanceParams": [
+        {}
+      ],
+      "rollbackOnFailure": true,
+      "instanceId": null,
+      "vfModules": {
+        "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0": {
+          "vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0ahubg": {
+            "modelInfo": {
+              "modelCustomizationName": "VprobeNcVnf..FE_base_module..module-0",
+              "modelCustomizationId": "4d0818cf-eaa9-4a3f-89c2-639953089e14",
+              "modelInvariantId": "29b6fa3c-aeb3-4103-b3f7-6f98e097b005",
+              "modelVersionId": "c5b26cc1-a66f-4b69-aa23-6abc7c647c88",
+              "modelName": "VprobeNcVnf..FE_base_module..module-0",
+              "modelType": "vfModule",
+              "modelVersion": "1"
+            },
+            "instanceName": "hvf6arlba007_lba_Base_02",
+            "action": "Create",
             "lcpCloudRegionId": "hvf6",
             "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
             "instanceParams": [
               "modelType": "vfModule",
               "modelVersion": "1"
             },
-            "instanceName": "my_hvf6arlba007_lba_dj_01",
+            "instanceName": "my_hvf6arlba007_lba_dj_02",
             "action": "Create",
             "lcpCloudRegionId": "hvf6",
             "tenantId": "4914ab0ab3a743e58f0eefdacc1dde77",
index 71ba536..0496266 100644 (file)
@@ -20,7 +20,7 @@
   "tenantId" : "c85f0e80-0636-44a4-8cb2-4ec00d056e79",
   "tenantName" : "Hedvika Wendelin",
   "bulkSize": "1",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true
 }
 
index 4306752..d458b63 100644 (file)
@@ -38,7 +38,7 @@
   "tenantId" : "c85f0e80-0636-44a4-8cb2-4ec00d056e79",
   "tenantName" : "Hedvika Wendelin",
   "bulkSize": "1",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte": true
 }
 
index ac5f7fa..9cbbfce 100644 (file)
@@ -67,5 +67,5 @@
   "isALaCarte": true,
   "orchStatus": "Active",
   "modelInavariantId": "6b528779-44a3-4472-bdff-9cd15ec93450",
-  "testApi": "VNF_API"
+  "testApi": "GR_API"
 }
\ No newline at end of file
index cf805b7..2fdda8f 100644 (file)
@@ -15,7 +15,7 @@
   "aicZoneName":null,
   "projectName":null,
   "rollbackOnFailure":null,
-  "isALaCarte":false,
+  "isALaCarte":true,
   "modelInfo":{
     "modelInvariantId":"d27e42cf-087e-4d31-88ac-6c4b7585f800",
     "modelVersionId": "6e59c5de-f052-46fa-aa7e-2fca9d674c44",
index a3fcd0e..2d71217 100644 (file)
   "rollbackOnFailure": true,
   "aicZoneName": null,
   "owningEntityName": "WayneHolland",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "modelInfo": {
     "modelInvariantId": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb",
     "modelVersionId": "f028b2e2-7080-4b13-91b2-94944d4c42d8",
diff --git a/vid-ext-services-simulator/src/main/resources/download_files/service-PASQUALEVmxVpeBvService488-csar-annotations.zip b/vid-ext-services-simulator/src/main/resources/download_files/service-PASQUALEVmxVpeBvService488-csar-annotations.zip
deleted file mode 100644 (file)
index a1f1f5d..0000000
Binary files a/vid-ext-services-simulator/src/main/resources/download_files/service-PASQUALEVmxVpeBvService488-csar-annotations.zip and /dev/null differ
diff --git a/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar.zip b/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar.zip
deleted file mode 100644 (file)
index 2967a50..0000000
Binary files a/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar.zip and /dev/null differ
diff --git a/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar_ecomp_false6.zip b/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar_ecomp_false6.zip
deleted file mode 100644 (file)
index dfd9298..0000000
Binary files a/vid-ext-services-simulator/src/main/resources/download_files/service-vDOROTHEASrv-csar_ecomp_false6.zip and /dev/null differ
index fa628d4..3b42a1c 100644 (file)
@@ -215,15 +215,20 @@ describe('A la carte', function () {
       });
     });
 
-    it(`VFModule a-la-carte`, () => {
-      var timeBomb = new Date('12/09/2018');
-      if (new Date() < timeBomb) {
-        return;
-      }
+    it(`Add ALaCarte VfModule Without LcpRegion Tenant Id And Legacy`, () => {
+      addAlacarteVfmoduleByFlag(true, 'redux-a-la-carte-no-lcp-tenant.json');
+    });
+
+    it(`Add ALaCarte VfModule With LcpRegion Tenant Id And Legacy`, () => {
+      addAlacarteVfmoduleByFlag(false, 'redux-a-la-carte.json');
+    });
+
+    function addAlacarteVfmoduleByFlag  (flag: boolean, expectedJsonFile: string) {
       cy.readFile('cypress/support/jsonBuilders/mocks/jsons/emptyServiceRedux.json').then((res) => {
         cy.setTestApiParamToGR();
         res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.vidNotions.instantiationType = 'ALaCarte';
         res.service.serviceHierarchy['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].service.inputs = null;
+        res.global['flags'] = { 'FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF' : flag };
         cy.setReduxState(<any>res);
         cy.openIframe('app/ui/#/servicePlanning?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd');
 
@@ -241,31 +246,30 @@ describe('A la carte', function () {
               '2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2',
             ];
 
-            cy.addALaCarteVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false)
+            cy.addALaCarteVfModule(vnfName, vfModulesNames[0], 'mimazepubi', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, false, flag)
+            .then(() => {
+              cy.addALaCarteVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false, flag)
               .then(() => {
-                cy.addALaCarteVfModule(vnfName, vfModulesNames[1], 'puwesovabe', 'AAIAIC25', 'my region', 'USP-SIP-IC-24335-T-01', true, true, false)
-                  .then(() => {
-                    cy.addALaCarteVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true)
-                      .then(() => {
-                        cy.getReduxState().then((state) => {
-                          const vfModules = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs[vnfName].vfModules;
-                          cy.readFile('../vid-automation/src/test/resources/a-la-carte/redux-a-la-carte.json').then((file) => {
-                            for (let vfModulesName of vfModulesNames) {
-                              const vfModule = vfModules[vfModulesName];
-                              let vfModuleObject = vfModule[Object.keys(vfModule)[0]];
-                              file.vnfs[vnfName].vfModules[vfModulesName][vfModulesName].action = "Create";
-                              cy.deepCompare(vfModuleObject, file.vnfs[vnfName].vfModules[vfModulesName][vfModulesName]);
-                            }
-                          });
-                        });
-                      });
+                cy.addALaCarteVfModule(vnfName, vfModulesNames[2], 'bnmgtrx', 'hvf6', '', 'AINWebTool-15-D-iftach', false, false, true, flag)
+                .then(() => {
+                  cy.getReduxState().then((state) => {
+                    const vfModules = state.service.serviceInstance['2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd'].vnfs[vnfName].vfModules;
+                    cy.readFile('../vid-automation/src/test/resources/a-la-carte/' + expectedJsonFile).then((file) => {
+                      for (let vfModulesName of vfModulesNames) {
+                        const vfModule = vfModules[vfModulesName];
+                        let vfModuleObject = vfModule[Object.keys(vfModule)[0]];
+                        file.vnfs[vnfName].vfModules[vfModulesName][vfModulesName].action = "Create";
+                        cy.deepCompare(vfModuleObject, file.vnfs[vnfName].vfModules[vfModulesName][vfModulesName]);
+                      }
+                    });
                   });
+                });
               });
+            });
           });
         });
       });
-    });
-
+    };
 
     function changeServiceEcompNamingToTrue(obj: ServiceModel) {
       obj.service.serviceEcompNaming = "true";
@@ -283,8 +287,5 @@ describe('A la carte', function () {
         .get('.error').contains(INSTANCE_NAME_NOT_MANDATORY_MESSAGE);
     }
 
-
-
-
   });
 });
index 4276965..b1671a4 100644 (file)
@@ -63,13 +63,13 @@ describe('Browse SDC', function () {
 
   });
 
-  it(`browse sdc should open instantiation template modal if service hasTemplate is true`, function () {
+  it(`browse sdc should open instantiation template modal if service isInstantiationTemplateExists is true`, function () {
     const SERVICE_MODEL_ID: string = '74fa72dd-012b-49c3-800d-06b12bcaf1a0';
 
     cy.readFile('cypress/support/jsonBuilders/mocks/jsons/bug616888/list-services.json').then((res) => {
-      res.services = res.services.map((service: { uuid: string, hasTemplate: boolean }) => {
+      res.services = res.services.map((service: { uuid: string, isInstantiationTemplateExists: boolean }) => {
         if (service.uuid === SERVICE_MODEL_ID) {
-          service.hasTemplate = true;
+          service.isInstantiationTemplateExists = true;
         }
         return service;
       });
@@ -98,6 +98,45 @@ describe('Browse SDC', function () {
     });
   });
 
+  it(`browse sdc open create new service instance flow`, function () {
+    const MACRO_FOR_NEW_FLOW_ID: string = '745d1bf1-9ed1-413f-8111-f1e984ad63fb';
+
+    cy.initGetAAISubDetails();
+
+    cy.readFile('cypress/support/jsonBuilders/mocks/jsons/aaiGetModelsByServiceType.json').then((res) => {
+      jsonBuilderAndMock.basicJson(res,
+        Cypress.config('baseUrl') + '/aai_get_models_by_service_type/**',
+        200,
+        0,
+        'aaiGetModelByServiceType');
+    });
+
+    cy.readFile('cypress/support/jsonBuilders/mocks/jsons/bug616888/Dror_service1806_Macro1.json').then((res) => {
+      jsonBuilderAndMock.basicJson(res,
+        Cypress.config('baseUrl') + '/rest/models/services/' + MACRO_FOR_NEW_FLOW_ID,
+        200,
+        0,
+        'MACRO_FOR_NEW_FLOW');
+    });
+
+    cy.get('span').contains('Create New Service Instance').click({force: true})
+      .selectDropdownOptionByText('subscriberName', 'SILVIA ROBBINS');
+    cy.get('button').contains('Submit').click({force: true});
+    cy.selectDropdownOptionByText('serviceType', 'TYLER SILVIA');
+    cy.get('button').contains('Submit').click({force: true});
+    cy.wait("@aaiGetModelByServiceType").then(() => {
+      cy.getElementByDataTestsId('deploy-' + MACRO_FOR_NEW_FLOW_ID).click({force: true});
+      cy.get('button').contains('Deploy').eq(0).click({force: true});
+      cy.get('iframe').then(function ($iframe) {
+          expect($iframe.attr('src')).to.contain(`app/ui/#/servicePopup?serviceModelId=74fa72dd-012b-49c3-800d-06b12bcaf1a0`);
+      });
+    });
+
+    cy.visit("welcome.htm"); //relaod page to not break the following tests
+
+  });
+
+
   it(`browse sdc of service without instantiationType open aLaCarte popup`, function () {
     const VERY_OLD_SERVICE_UUID: string = "09c476c7-91ae-44b8-a731-04d8d8fa3695";
     const TEST_MOCKS_PATH = "cypress/support/jsonBuilders/mocks/jsons/bug_aLaCarteServiceWrongPopup/";
index cf870b7..4a8b89a 100644 (file)
@@ -350,7 +350,7 @@ describe('Drawing board', function () {
         cy.drawingBoardTreeClickOnContextMenuOptionByName('Remove');
 
         cy.get('.title').contains('Remove VNF');
-        cy.get('.sdc-button').contains('Remove VNF').click();
+        cy.get('.custom-button').contains('Remove VNF').click();
         // assert vfModules are disabled after remove parent vnf
         cy.get('.tree-node-disabled div[data-tests-id="node-2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1"]')
           .should('be.visible');
@@ -6762,7 +6762,7 @@ describe('Drawing board', function () {
                       "supplementaryFile_hidden_content": "{\r\n  \"name\": \"a\",\r\n  \"value\": \"32\"\r\n}",
                       "supplementaryFileContent": {
                         "name": "a",
-                          "value": "32"
+                        "value": "32"
                       },
                       "supplementaryFileName": "sample.json",
                       "instanceParams": [
index 5afcc97..bb2c01a 100644 (file)
@@ -25,7 +25,7 @@ describe('Drawing Board: Instantiation Templates', function () {
 
       it(`Given a stored template - when click "deploy" - then a coherent request should be sent upon deploy`, () => {
 
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
         // Then...
         cy.getElementByDataTestsId("node-vProbe_NC_VNF 0").should('be.visible');
@@ -34,8 +34,9 @@ describe('Drawing Board: Instantiation Templates', function () {
 
       it('Given a template - User can remove existing VNF', () => {
 
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
+        removeVNFWithVFModules('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0');
         removeVNFWithVFModules('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0');
 
         cy.getDrawingBoardDeployBtn().click();
@@ -46,43 +47,52 @@ describe('Drawing Board: Instantiation Templates', function () {
       });
 
       it('Given a template - User can add new VNF', () => {
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
         // add new node
         addNewNode('node-vProbe_NC_VNF 0-add-btn')
           .fillVnfPopup()
           .getDrawingBoardDeployBtn().click()
           .wait('@expectedPostAsyncInstantiation').then(xhr => {
-            const vnfRequest = bodyOf(xhr).vnfs['vProbe_NC_VNF 0_1'];
-
-            expect(vnfRequest.action).equals("Create");
-            expect(vnfRequest.rollbackOnFailure).equals("true");
-            expect(vnfRequest.originalName).equals("vProbe_NC_VNF 0");
-            expect(vnfRequest.productFamilyId).equals("a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb");
-            expect(vnfRequest.lcpCloudRegionId).equals("hvf6");
-            expect(vnfRequest.lineOfBusiness).equals("zzz1");
-            expect(vnfRequest.platformName).equals("xxx1");
-            expect(vnfRequest.tenantId).equals("229bcdc6eaeb4ca59d55221141d01f8e");
+          const vnfRequest = bodyOf(xhr).vnfs['vProbe_NC_VNF 0_2'];
+
+          expect(vnfRequest.action).equals("Create");
+          expect(vnfRequest.rollbackOnFailure).equals("true");
+          expect(vnfRequest.originalName).equals("vProbe_NC_VNF 0");
+          expect(vnfRequest.productFamilyId).equals("a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb");
+          expect(vnfRequest.lcpCloudRegionId).equals("hvf6");
+          expect(vnfRequest.lineOfBusiness).equals("zzz1");
+          expect(vnfRequest.platformName).equals("xxx1");
+          expect(vnfRequest.tenantId).equals("229bcdc6eaeb4ca59d55221141d01f8e");
+
+
+          // check instance name not change if empty
+          cy.editNode('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0', 0)
+            .clearInput('instanceName');
+          cy.getElementByDataTestsId('form-set').click({force: true}).then((done) => {
+            cy.editNode('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0', 0)
+              .getElementByDataTestsId('instanceName').should('be.empty')
+          });
         });
       });
 
       it('Given a template - User can Duplicate VNF', () => {
         const numberOfDuplicate: number = 4;
-        loadDrawingBoardWithRecreateMode();
-        nodeAction('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0', 'Duplicate')
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
+        cy.nodeAction('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0', 'Duplicate')
           .getElementByDataTestsId('duplicate-amount-vfmodules').select(numberOfDuplicate.toString())
           .getTagElementContainsText('button', 'Duplicate').click()
           .getDrawingBoardDeployBtn().click()
           .wait('@expectedPostAsyncInstantiation').then(xhr => {
-            expect(Object.keys(bodyOf(xhr).vnfs).length).equals(numberOfDuplicate + 1);
+          expect(Object.keys(bodyOf(xhr).vnfs).length).equals(numberOfDuplicate + 2);
         });
       });
 
       it('Given a stored template - when "edit" vnf and vfmodules are opened - then template’s details are visible as expected and deploy without changes', () => {
 
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
         // Then...
-        editNode("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0")
+        cy.editNode("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0")
           .getElementByDataTestsId("instanceName").should('have.value', 'hvf6arlba007')
           .getElementByDataTestsId("productFamily").should('contain', 'Emanuel')
           .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1')
@@ -92,30 +102,27 @@ describe('Drawing Board: Instantiation Templates', function () {
           .checkPlatformValue('xxx1')
           .getElementByDataTestsId("cancelButton").click();
 
-        editNode("node-c5b26cc1-a66f-4b69-aa23-6abc7c647c88-vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0")
+        cy.editNode("node-c5b26cc1-a66f-4b69-aa23-6abc7c647c88-vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0")
           .getElementByDataTestsId("instanceName").should('have.value', 'hvf6arlba007_lba_Base_01')
-          .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6')
-          .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1')
           .getElementByDataTestsId("rollback").should('contain', 'Rollback')
           .getElementByDataTestsId("cancelButton").click();
 
-        editNode("node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1")
+        cy.editNode("node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1")
           .getElementByDataTestsId("instanceName").should('have.value', 'my_hvf6arlba007_lba_dj_01')
           .getElementByDataTestsId("volumeGroupName").should('have.value', 'my_special_hvf6arlba007_lba_dj_01_vol')
-          .getElementByDataTestsId("lcpRegion").should('contain', 'hvf6')
-          .getElementByDataTestsId("tenant").should('contain', 'DN5242-Nov21-T1')
           .getElementByDataTestsId("rollback").should('contain', 'Rollback')
           .getElementByDataTestsId("sdncPreLoad").should('have.value', 'on')
           .getElementByDataTestsId("cancelButton").click();
 
         assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd([
           {path: [...vnfPath, "vnfStoreKey"], value: "vProbe_NC_VNF 0"}, // side-effect
+          {path: [...vnfPath2, "vnfStoreKey"], value: "vProbe_NC_VNF 0_1"},
         ]);
       });
 
       it(`Given a stored template - when "edit" service is opened - then template’s details are visible as expected`, function () {
 
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
         cy.openServiceContextMenu()
           .getElementByDataTestsId("context-menu-header-edit-item").click()
@@ -129,25 +136,23 @@ describe('Drawing Board: Instantiation Templates', function () {
       });
 
       it(`Given a stored template - add one VfModule, edit its details, and deploy - deploy is added with the vfModule details`, () => {
-        loadDrawingBoardWithRecreateMode();
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
         let newVfModuleName = "new.vfmodule.name";
         let module1ModelId = "VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1";
         let module1CustomizationId = `vprobe_nc_vnf0..${module1ModelId}`;
 
         // Click target VNF on right tree
-        cy.getElementByDataTestsId('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0').click();
+        cy.getElementByDataTestsId('node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0').first().click();
 
         // Click [+] vfModule on left tree
         cy.drawingBoardPressAddButtonByElementName(`node-${module1CustomizationId}`)
           .click({force: true});
 
-        editNode(`node-c09e4530-8fd8-418f-9483-2f57ce927b05-${module1CustomizationId}`, 1);
-          cy.clearInput("instanceName");
-          cy.typeToInput("instanceName", newVfModuleName);
-          cy.selectDropdownOptionByText('lcpRegion', 'hvf6');
-          cy.selectDropdownOptionByText('tenant', 'DN5242-Nov21-T1');
-          cy.getElementByDataTestsId('form-set').click();
+        cy.editNode(`node-c09e4530-8fd8-418f-9483-2f57ce927b05-${module1CustomizationId}`, 1);
+        cy.clearInput("instanceName");
+        cy.typeToInput("instanceName", newVfModuleName);
+        cy.getElementByDataTestsId('form-set').click();
 
         // Then...
         cy.getReduxState().then((state) => {
@@ -166,13 +171,12 @@ describe('Drawing Board: Instantiation Templates', function () {
             {
               instanceName: newVfModuleName,
               volumeGroupName: `${newVfModuleName}_vol`,
-              lcpCloudRegionId: "hvf6",
-              tenantId: "4914ab0ab3a743e58f0eefdacc1dde77",
             }
           );
 
           assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd([
             {path: [...vnfPath, "vnfStoreKey"], value: "vProbe_NC_VNF 0"},   // side-effect
+            {path: [...vnfPath2, "vnfStoreKey"], value: "vProbe_NC_VNF 0_1"},
             {path: ["existingNames", newVfModuleName], value: ""},
             {path: ["existingNames", `${newVfModuleName}_vol`], value: ""},
             {path: latestVfModule_1Path, value: latestVfModule_1ExpectedValue},
@@ -184,8 +188,8 @@ describe('Drawing Board: Instantiation Templates', function () {
 
       it('Given a template - User can remove existing vfmodule', function () {
 
-        loadDrawingBoardWithRecreateMode();
-        nodeAction('node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1', 'Remove');
+        cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
+        cy.nodeAction('node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1', 'Remove');
         let removed_vfModule_Path = [
           ...vnfPath, "vfModules",
           "vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1",
@@ -193,6 +197,7 @@ describe('Drawing Board: Instantiation Templates', function () {
 
         assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd([
           {path: [...vnfPath, "vnfStoreKey"], value: "vProbe_NC_VNF 0"}, // side-effect
+          {path: [...vnfPath2, "vnfStoreKey"], value: "vProbe_NC_VNF 0_1"},
           {path: [...removed_vfModule_Path], value: undefined},
         ]);
       });
@@ -204,7 +209,7 @@ describe('Drawing Board: Instantiation Templates', function () {
 
         it(`Given a stored template - edit service vnf and vfmodule ${testCase.desc} - deploy request should be ${testCase.desc}`, function () {
 
-          loadDrawingBoardWithRecreateMode();
+          cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
 
           //edit service
           cy.openServiceContextMenu();
@@ -216,7 +221,7 @@ describe('Drawing Board: Instantiation Templates', function () {
           cy.getElementByDataTestsId('form-set').click();
 
           // edit vnf
-          editNode("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0");
+          cy.editNode("node-21ae311e-432f-4c54-b855-446d0b8ded72-vProbe_NC_VNF 0");
           if (testCase.modifySomeValues) {
             cy.selectPlatformValue('platform');
             cy.selectDropdownOptionByText("tenant", "CESAR-100-D-spjg61909");
@@ -224,7 +229,7 @@ describe('Drawing Board: Instantiation Templates', function () {
           cy.getElementByDataTestsId('form-set').click();
 
           //edit vf module
-          editNode("node-c5b26cc1-a66f-4b69-aa23-6abc7c647c88-vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0");
+          cy.editNode("node-c5b26cc1-a66f-4b69-aa23-6abc7c647c88-vprobe_nc_vnf0..VprobeNcVnf..FE_base_module..module-0");
           if (testCase.modifySomeValues) {
             cy.getElementByDataTestsId('sdncPreLoad').click();
           }
@@ -251,9 +256,9 @@ describe('Drawing Board: Instantiation Templates', function () {
 
       });
 
-      it(`Given a stored template of Network - - it is loaded`,  () => {
+      it(`Given a stored template of Network - - it is loaded`, () => {
 
-        loadDrawingBoardWithRecreateModeNetwork();
+        cy.loadDrawingBoardWithRecreateModeNetwork(templateWithNetworkSetup);
 
         // Then...
         cy.getElementByDataTestsId("node-SR-IOV Provider 2-1").should('be.visible');
@@ -261,11 +266,11 @@ describe('Drawing Board: Instantiation Templates', function () {
         assertThatBodyFromDeployRequestEqualsToTemplateFromBackEnd_network();
       });
 
-      it(`Given a stored template of Network - User can remove existing network`,  () => {
+      it(`Given a stored template of Network - User can remove existing network`, () => {
 
-        loadDrawingBoardWithRecreateModeNetwork();
+        cy.loadDrawingBoardWithRecreateModeNetwork(templateWithNetworkSetup);
 
-        nodeAction('node-01f4c475-3f89-4f00-a2f4-39a873dba0ae-SR-IOV Provider 2-1', 'Remove');
+        cy.nodeAction('node-01f4c475-3f89-4f00-a2f4-39a873dba0ae-SR-IOV Provider 2-1', 'Remove');
         let removed_network_Path = [
           "networks", "SR-IOV Provider 2-1",
         ];
@@ -282,13 +287,13 @@ describe('Drawing Board: Instantiation Templates', function () {
 
       it('Given a template - User can add a new network', () => {
 
-        loadDrawingBoardWithRecreateModeNetwork();
+        cy.loadDrawingBoardWithRecreateModeNetwork(templateWithNetworkSetup);
 
         // add new node
         addNewNode('node-SR-IOV Provider 2-1-add-btn')
-        .fillNetworkPopup()
-        .getDrawingBoardDeployBtn().click()
-        .wait('@expectedPostAsyncInstantiation').then(xhr => {
+          .fillNetworkPopup()
+          .getDrawingBoardDeployBtn().click()
+          .wait('@expectedPostAsyncInstantiation').then(xhr => {
           const networkRequest = bodyOf(xhr).networks['SR-IOV Provider 2-1_1'];
 
           expect(networkRequest.action).equals("Create");
@@ -324,58 +329,18 @@ const vnfPath = [
   "vnfs", "vProbe_NC_VNF 0"
 ];
 
-function loadDrawingBoardWithRecreateMode() {
-  loadDrawingBoardWithRecreateModeInternal(
-    '../../' + templateWithVnfSetup.instanceTemplateFile,
-    templateWithVnfSetup.serviceModelId,
-    templateWithVnfSetup.serviceModelFile);
-}
-
-function loadDrawingBoardWithRecreateModeNetwork() {
-  loadDrawingBoardWithRecreateModeInternal(
-    '../../' + templateWithNetworkSetup.instanceTemplateFile,
-    templateWithNetworkSetup.serviceModelId,
-    templateWithNetworkSetup.serviceModelFile);
-}
-
-function loadDrawingBoardWithRecreateModeInternal(instanceTemplate: string, serviceModelIdToLoad: any, serviceModel: string) {
-  const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b";
-
-  const drawingBoardAction = `RECREATE`;
-  const templateTopologyEndpoint = "templateTopology";
-  cy.route(`**/rest/models/services/${serviceModelIdToLoad}`,
-    'fixture:' + serviceModel)
-    .as('serviceModel');
-
-  cy.route(`**/instantiationTemplates/${templateTopologyEndpoint}/${templateUuid}`,
-    'fixture:' + instanceTemplate)
-    .as('templateTopology');
-
-  // When...
-
-  cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` +
-    `?jobId=${templateUuid}` +
-    `&serviceModelId=${serviceModelIdToLoad}`);
-
-  cy.wait('@serviceModel');
-  cy.wait('@templateTopology');
-}
+const vnfPath2 = [
+  "vnfs", "vProbe_NC_VNF 0_1"
+];
 
-function nodeAction(dataTestId: string, action: string, index ?: number) {
-  return cy.drawingBoardTreeOpenContextMenuByElementDataTestId(dataTestId, index)
-    .drawingBoardTreeClickOnContextMenuOptionByName(action)
-}
 
-function editNode(dataTestId: string, index ?: number) {
-  return nodeAction(dataTestId, 'Edit', index);
-}
 
 function addNewNode(dataTestId: string) {
   return cy.getElementByDataTestsId(dataTestId).click({force: true})
 }
 
 function removeVNFWithVFModules(dataTestId: string) {
-  return nodeAction(dataTestId, 'Remove')
+  return cy.nodeAction(dataTestId, 'Remove')
     .getTagElementContainsText('button', 'Remove VNF').click()
 }
 
@@ -448,6 +413,7 @@ function mockAsyncBulkResponse() {
     url: Cypress.config('baseUrl') + '/asyncInstantiation/bulk',
     method: 'POST',
     status: 200,
-    response: "[]",
+    response: true,
   }).as("expectedPostAsyncInstantiation");
 }
+
index 0db1b09..f76babe 100644 (file)
@@ -71,7 +71,7 @@ describe('Template', () => {
 
     cy.route(Cypress.config('baseUrl') + "/getuserID", 'us16807000');
 
-    cy.openPopupIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true&hasTemplate=true');
+    cy.openPopupIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true&isInstantiationTemplateExists=true');
 
   });
 
@@ -94,17 +94,15 @@ describe('Template', () => {
     cy.get(`#header-instantiationStatus`).contains('Instantiation Status');
     cy.get(`#header-region`).contains('Region');
     cy.get(`#header-tenant`).contains('Tenant');
-    cy.get(`#header-aicZone`).contains('AIC Zone');
 
     // check table body row
     cy.getElementByDataTestsId(`userId-${templateJobIdFromE2EFile}`).contains('16807000');
-    cy.getElementByDataTestsId(`createDate-${templateJobIdFromE2EFile}`).contains('2019-12-26 11:57:05');
+    cy.getElementByDataTestsId(`createDate-${templateJobIdFromE2EFile}`).contains(/2019-12-26 [0-9]{1,2}:57:05/); //timezone insensitive
     cy.getElementByDataTestsId(`instanceName-${templateJobIdFromE2EFile}`).contains('SERVICE_NAME');
     cy.getElementByDataTestsId(`instantiationStatus-${templateJobIdFromE2EFile}`).contains('IN_PROGRESS');
     cy.getElementByDataTestsId(`summary-${templateJobIdFromE2EFile}`).contains('vnf: 1, vfModule: 2, volumeGroup: 1');
     cy.getElementByDataTestsId(`region-${templateJobIdFromE2EFile}`).contains('hvf3 (SOMENAME)');
     cy.getElementByDataTestsId(`tenant-${templateJobIdFromE2EFile}`).contains('greatTenant');
-    cy.getElementByDataTestsId(`aicZone-${templateJobIdFromE2EFile}`).contains('NFTJSSSS-NFT1');
 
 
     //check load button is disabled
index e544720..693e5f5 100644 (file)
@@ -39,6 +39,7 @@ describe('Retry Page', function () {
       res.vnfs["2017-388_PASQUALE-vPE 0"].action = 'Create';
       res.vnfs["2017-488_PASQUALE-vPE 0"].action = 'Create';
       res.networks["ExtVL 0"].action = 'Create';
+      res.networks["ExtVL 0"].isFailed = true;
       res.networks["ExtVL 0"].statusMessage = 'Network instantiation failed message';
 
       // Adding VFModule with isFailed.
@@ -56,7 +57,7 @@ describe('Retry Page', function () {
 
     cy.openIframe(`app/ui/#/servicePlanning/RETRY_EDIT?serviceModelId=${SERVICE_MODEL_ID}&subscriberId=${SUBSCRIBER_ID}&serviceType=${SERVICE_TYPE}&serviceInstanceId=${SERVICE_INSTANCE_ID}&jobId=${JOB_ID}`);
 
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').click();
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').eq(0).click();
 
     cy.get('.failed-msg').should('have.length', 5);
     cy.get('.newIcon').should('have.length', 4);
@@ -112,6 +113,7 @@ describe('Retry Page', function () {
       // Adding VFModule with isFailed.
       res.vnfs["2017-488_PASQUALE-vPE 0"].vfModules["2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0"]["2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot"].isFailed = true;
       res.vnfs["2017-488_PASQUALE-vPE 0"].vfModules["2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0"]["2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0uvfot"].action = 'Create';
+      res.networks["ExtVL 0"].isFailed = true;
 
       cy.readFile('cypress/support/jsonBuilders/mocks/jsons/responceForFailedInstance.json').then((res) => {
         jsonBuilderAndMock.basicJson(
@@ -133,7 +135,7 @@ describe('Retry Page', function () {
 
     cy.openIframe(`app/ui/#/servicePlanning/RETRY?serviceModelId=${SERVICE_MODEL_ID}&subscriberId=${SUBSCRIBER_ID}&serviceType=${SERVICE_TYPE}&serviceInstanceId=${SERVICE_INSTANCE_ID}&jobId=${JOB_ID}`);
 
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').click();
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').eq(0).click();
 
     cy.get('.failed-msg').should('have.length', 4);
     cy.get('.newIcon').should('have.length', 4);
diff --git a/vid-webpack-master/cypress/integration/iFrames/sdncPreload.e2e.ts b/vid-webpack-master/cypress/integration/iFrames/sdncPreload.e2e.ts
new file mode 100644 (file)
index 0000000..877506c
--- /dev/null
@@ -0,0 +1,92 @@
+describe('SDNC preload ', () => {
+
+  beforeEach(() => {
+    cy.clearSessionStorage();
+    cy.setTestApiParamToGR();
+    cy.initAAIMock();
+    cy.initGetAAISubDetails();
+    cy.initVidMock();
+    cy.initDrawingBoardUserPermission();
+    cy.login();
+  });
+
+  afterEach(() => {
+    cy.screenshot();
+  });
+
+  it('feature toggle is on and SDNC is checked then SDNC preload file is enable : upload success' , () => {
+    mockPreloadResult(true, 200);
+    cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
+    cy.editNode("node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1");
+    checkUploadLinkLogic();
+
+    uploadFile().then(() => {
+      cy.get('.sdc-modal__content').should('contain', 'The pre-load file(s) have been uploaded successfully.');
+      cy.getElementByDataTestsId('button-ok').click()
+        .getElementByDataTestsId('sdnc_pereload_upload_link').should('contain', 'Upload another')
+    });
+  });
+
+  it('feature toggle is on and SDNC is checked then SDNC preload file is enable : upload fail', () => {
+    mockPreloadResult(false, 200);
+    cy.loadDrawingBoardWithRecreateMode(templateWithVnfSetup);
+
+    cy.editNode("node-c09e4530-8fd8-418f-9483-2f57ce927b05-vprobe_nc_vnf0..VprobeNcVnf..FE_Add_On_Module_vlbagent_eph..module-1");
+    checkUploadLinkLogic();
+
+    uploadFile().then(() => {
+      cy.get('.sdc-modal__content').should('contain', 'Failed to upload one or more of the files, please retry.');
+      cy.getElementByDataTestsId('button-ok').click()
+        .getElementByDataTestsId('sdnc_pereload_upload_link').should('contain', 'Upload')
+    });
+  });
+});
+
+
+let apiTestResources = '../vid-automation/src/test/resources/asyncInstantiation/';
+
+const templateWithVnfSetup = {
+  serviceModelId: '6cfeeb18-c2b0-49df-987a-da47493c8e38',
+  instanceTemplateFile: apiTestResources + 'templates__instance_template.json',
+  instanceTemplateSetWithoutModifyFile: apiTestResources + 'templates__instance_from_template__set_without_modify1.json',
+  serviceModelFile: '../support/jsonBuilders/mocks/jsons/instantiationTemplates/templates__service_model.json',
+};
+
+function mockAsyncBulkResponse() {
+  cy.server().route({
+    url: Cypress.config('baseUrl') + '/asyncInstantiation/bulk',
+    method: 'POST',
+    status: 200,
+    response: true,
+  }).as("expectedPostAsyncInstantiation");
+}
+
+function mockPreloadResult(response: boolean, status?: number) {
+  cy.server().route({
+    url: Cypress.config('baseUrl') + '/preload',
+    method: 'POST',
+    status: status ? status : 200,
+    response: response,
+  }).as("preload");
+}
+
+
+function uploadFile() {
+  // @ts-ignore
+  return new Promise((resolve) => {
+    const fileName = '../support/uploadFiles/sdncPreLoadFileExample.json';
+    cy.fixture(fileName).then(fileContent => {
+      // @ts-ignore
+      cy.get('input[type=file]').eq(0).upload({fileContent, fileName, mimeType: 'application/json'}).then(() => {
+        resolve();
+      });
+    })
+  });
+}
+
+function checkUploadLinkLogic() {
+  cy.getElementByDataTestsId('sdnc_pereload_upload_link').should('contain', 'Upload').should('not.have.class', 'disabled')
+    .getElementByDataTestsId('sdncPreLoad').click()
+    .getElementByDataTestsId('sdnc_pereload_upload_link').should('contain', 'Upload').should('have.class', 'disabled')
+    .getElementByDataTestsId('sdncPreLoad').click()
+}
index 4b27ad0..06f5a23 100644 (file)
@@ -36,7 +36,7 @@ describe('Service popup', function () {
         res1.global.flags = {};
         res1.global.flags["FLAG_2004_INSTANTIATION_TEMPLATES_POPUP"] = true;
         cy.setReduxState(<any>res1);
-        cy.openPopupIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true&hasTemplate=true');
+        cy.openPopupIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true&isInstantiationTemplateExists=true');
         cy.getElementByDataTestsId('templateButton').should('be.visible')
       });
     });
@@ -95,13 +95,6 @@ describe('Service popup', function () {
       });
     });
 
-    it('when open service popup should show showPrevious button', () => {
-      cy.openPopupIframe('/app/ui/#/servicePopup?serviceModelId=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd&isCreate=true');
-      cy.getElementByDataTestsId('ShowPreviousInstancesButton').contains('Previous Instantiation').click();
-
-    })
-
-
   });
 });
 
index 0973447..ad15ce3 100644 (file)
@@ -16,6 +16,8 @@ export const initServicePlanning = function (viewOrEdit: string, customModelFile
   }
 
   cy.readFile('../vid-automation/src/test/resources/aaiGetInstanceTopology/ServiceTreeWithMultipleChildren_serviceModel.json').then((res) => {
+    res.service.instantiationType = "A-La-Carte";
+    res.service.vidNotions.instantiationType = "ALaCarte";
     jsonBuilderAndMock.basicJson(
       res,
       Cypress.config('baseUrl') + "/rest/models/services/6e59c5de-f052-46fa-aa7e-2fca9d674c44",
@@ -133,7 +135,7 @@ describe('View Edit Page: Upgrade VFModule', function () {
 
     beforeEach(() => {
       cy.clearSessionStorage();
-      cy.setTestApiParamToVNF();
+      cy.setTestApiParamToGR();
       cy.initVidMock();
       cy.login();
     });
@@ -200,8 +202,9 @@ describe('View Edit Page: Upgrade VFModule', function () {
   }
 
   function verifyMenuActionUpgradeDoesNotExist() {
-    cy.getElementByDataTestsId('node-undefined-dc229cd8-c132-4455-8517-5c1787c18b14-menu-btn').click()
-    .getElementByDataTestsId('context-menu-upgrade').should('not.exist');
+    cy.getElementByDataTestsId('node-522159d5-d6e0-4c2a-aa44-5a542a12a830-vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1-menu-btn').click().then(() => {
+      cy.getElementByDataTestsId('context-menu-upgrade').should('not.exist');
+    });
   }
 
   function setLatestVersionMockToEmptyResponse(serviceUuid: string) {
index 60b2e12..de5facf 100644 (file)
@@ -113,13 +113,13 @@ describe('View only drawing board', function () {
     cy.getElementByDataTestsId('node-2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1').find(`[data-tests-id='node-type-indicator']`).should('have.text', 'M');
 
     //testing right side
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find(`[data-tests-id='node-type-indicator']`).should('have.text', 'VNF');
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').click({force: true});
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find(`[data-tests-id='node-type-indicator']`).should('have.length', 3).and('have.text', 'VNFVNFVNF');
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').eq(0).click({force: true});
     cy.getElementByDataTestsId('node-f8360508-3f17-4414-a2ed-6bc71161e8db-2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0').eq(0).find(`[data-tests-id='node-type-indicator']`).should('have.text', 'M');
 
     //check vnf node tree sub header
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find("[data-tests-id='status-property-orchStatus']").should('have.text', 'Created');
-    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find("[data-tests-id='status-property-provStatus']").should('have.text', '');
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find("[data-tests-id='status-property-orchStatus']").eq(0).should('have.text', 'Created');
+    cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find("[data-tests-id='status-property-provStatus']").eq(0).should('have.text', '');
     cy.getElementByDataTestsId('node-69e09f68-8b63-4cc9-b9ff-860960b5db09-2017-488_PASQUALE-vPE 0').find("[data-tests-id='status-property-inMaint']").should('not.exist');
 
     //check vf Module node tree sub header
index dc1b4bb..a0882f5 100644 (file)
@@ -12,7 +12,7 @@ describe('Vnf Groups', function () {
       cy.initAAIMock();
       cy.initVidMock();
       cy.permissionVidMock();
-      cy.setTestApiParamToVNF();
+      cy.setTestApiParamToGR();
       cy.login();
   });
 
@@ -20,6 +20,42 @@ describe('Vnf Groups', function () {
     cy.screenshot();
   });
 
+  function updateObject(obj: any, key: string, val: any, value:any) {
+    return JSON.parse(JSON.stringify(obj)
+    .replace(new RegExp(`"${key}":"${val}"`), `"${key}":"${value}"`))
+  }
+
+  function buildReduxStateWithServiceRespone(res: any, serviceId:string, isEcompGeneratedNaming:boolean) :void {
+    res = updateObject(res, "ecomp_generated_naming", !isEcompGeneratedNaming, isEcompGeneratedNaming);
+    cy.window().then((win) => {
+      win.sessionStorage.setItem('reduxState',  JSON.stringify({
+        "global": {
+          "name": null
+        },
+        "service": {
+          "serviceHierarchy": {
+            [serviceId] : res
+          },
+          "serviceInstance": {
+            [serviceId]: {
+              "modelInfo" : {
+                "modelVersionId" : serviceId
+              },
+              "existingVNFCounterMap": {},
+              "existingVnfGroupCounterMap": {},
+              "existingNetworksCounterMap": {},
+              "vnfs": {},
+              "vnfGroups": {},
+              "isEcompGeneratedNaming": isEcompGeneratedNaming,
+              "existingNames": {},
+              "vidNotions": res.service.vidNotions
+            }
+          }
+        }
+      }));
+    });
+  }
+
   describe('Vnf Group model basic view', function () {
 
       it('Vnf group open new view edit', function () {
@@ -36,7 +72,7 @@ describe('Vnf Groups', function () {
             "ServiceWithVnfGroup",
           );
 
-          cy.buildReduxStateWithServiceRespone(res, serviceId, false);
+          buildReduxStateWithServiceRespone(res, serviceId, false);
           cy.openIframe('app/ui/#/servicePlanning?serviceModelId=' + serviceId);
           cy.getElementByDataTestsId('node-' + groupName).find(`[data-tests-id='node-type-indicator']`).contains('G');
           cy.getElementByDataTestsId('node-' + groupName).contains('' + groupName);
index 6700ff4..529d96a 100644 (file)
@@ -480,7 +480,7 @@ describe('Drawing board : VRF', function () {
             "rollbackOnFailure": "true",
             "aicZoneName": null,
             "owningEntityName": "WayneHolland",
-            "testApi": "VNF_API",
+            "testApi": "GR_API",
             "modelInfo": {
               "modelInvariantId": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb",
               "modelVersionId": "f028b2e2-7080-4b13-91b2-94944d4c42d8",
index 51e084b..a646440 100644 (file)
@@ -32,7 +32,7 @@ describe('Spinner', function () {
             "error 500 asyncInstantiation");
           cy.openIframe('app/ui/#/instantiationStatus');
 
-          cy.get('.sdc-loader')
+          cy.get('.custom-loader')
             .and('be.visible');
 
         });
index 217efa1..a9b5aef 100644 (file)
@@ -1,11 +1,10 @@
+cypress/integration/iFrames/ala-carte.e2e.ts
 cypress/integration/iFrames/auditInfo.modal.e2e.ts
 cypress/integration/iFrames/browse-sdc.e2e.ts
+cypress/integration/iFrames/changeManagement.e2e.ts
 cypress/integration/iFrames/collectionResource.e2e.ts
+cypress/integration/iFrames/commitDialog.e2e.ts
 cypress/integration/iFrames/drawingBoard.e2e.ts
+cypress/integration/iFrames/instantiation-templates.e2e.ts
+cypress/integration/iFrames/instantiation.templates.modal.e2e.ts
 cypress/integration/iFrames/instantiationStatus.e2e.ts
-cypress/integration/iFrames/network.popup.e2e.ts
-cypress/integration/iFrames/permission.e2e.ts
-cypress/integration/iFrames/pnf.e2e.ts
-cypress/integration/iFrames/resume.e2e.ts
-cypress/integration/iFrames/retry.e2e.ts
-cypress/integration/iFrames/viewEdit.e2e.ts
diff --git a/vid-webpack-master/cypress/pipeline/run_group2.sh b/vid-webpack-master/cypress/pipeline/run_group2.sh
deleted file mode 100644 (file)
index 43cfbc6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-
-. $HOME/.nvm/nvm.sh
-
-set -x
-
-CYPRESS_HOME_DIR=$1
-TESTS_GROUP_FILE_1=cypress/pipeline/group1.txt
-TESTS_GROUP_FILE=cypress/pipeline/group2.generated.txt
-
-cd ${CYPRESS_HOME_DIR}
-
-# make group2 by "negating" group1.txt
-ls -1 cypress/integration/*/*.e2e.ts | comm -3 - ${TESTS_GROUP_FILE_1} > ${TESTS_GROUP_FILE}
-
-cat ${TESTS_GROUP_FILE}
-npm run cypress:headless --max-old-space-size=4096 -- --spec=$(cat ${TESTS_GROUP_FILE} | tr '\n' ',')
diff --git a/vid-webpack-master/cypress/pipeline/run_groupRemain.sh b/vid-webpack-master/cypress/pipeline/run_groupRemain.sh
new file mode 100644 (file)
index 0000000..51c3041
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+. $HOME/.nvm/nvm.sh
+
+set -x
+
+CYPRESS_HOME_DIR=$1
+REMAIN_TESTS_FILE=cypress/pipeline/remain.generated.txt
+ALL_TESTS_IN_GROUPS_FILE=cypress/pipeline/all_tests.txt
+
+cd ${CYPRESS_HOME_DIR}
+cat cypress/pipeline/group?.txt | sort > ${ALL_TESTS_IN_GROUPS_FILE}
+# make group2 by "negating" group1.txt
+ls -1 cypress/integration/*/*.e2e.ts | comm -3 - ${ALL_TESTS_IN_GROUPS_FILE} > ${REMAIN_TESTS_FILE}
+
+cat ${REMAIN_TESTS_FILE}
+npm run cypress:headless --max-old-space-size=4096 -- --spec=$(cat ${REMAIN_TESTS_FILE} | tr '\n' ',')
index c054b26..9126ae1 100644 (file)
@@ -5,7 +5,6 @@ declare namespace Cypress {
     clearSessionStorage: typeof clearSessionStorage;
     setTestApiParamToGR: typeof setTestApiParamToGR;
     setTestApiParamToVNF: typeof setTestApiParamToVNF;
-    buildReduxStateWithServiceRespone: typeof buildReduxStateWithServiceRespone;
   }
 }
 
@@ -44,42 +43,8 @@ function setTestApiParamToVNF() : void {
   });
 }
 
-function updateObject(obj: any, key: string, val: any, value:any) {
-  return JSON.parse(JSON.stringify(obj)
-    .replace(new RegExp(`"${key}":"${val}"`), `"${key}":"${value}"`))
-}
-
-function buildReduxStateWithServiceRespone(res: any, serviceId:string, isEcompGeneratedNaming:boolean) :void {
-  res = updateObject(res, "ecomp_generated_naming", !isEcompGeneratedNaming, isEcompGeneratedNaming);
-  cy.window().then((win) => {
-    win.sessionStorage.setItem('reduxState',  JSON.stringify({
-      "global": {
-        "name": null
-      },
-      "service": {
-        "serviceHierarchy": {
-          [serviceId] : res
-        },
-        "serviceInstance": {
-          [serviceId]: {
-            "existingVNFCounterMap": {},
-            "existingVnfGroupCounterMap": {},
-            "existingNetworksCounterMap": {},
-            "vnfs": {},
-            "vnfGroups": {},
-            "isEcompGeneratedNaming": isEcompGeneratedNaming,
-            "existingNames": {},
-            "vidNotions": res.service.vidNotions
-          }
-        }
-      }
-    }));
-  });
-}
-
 Cypress.Commands.add('setReduxState', setReduxState);
 Cypress.Commands.add('getReduxState', getReduxState);
 Cypress.Commands.add('clearSessionStorage', clearSessionStorage);
 Cypress.Commands.add('setTestApiParamToGR', setTestApiParamToGR);
 Cypress.Commands.add('setTestApiParamToVNF',setTestApiParamToVNF);
-Cypress.Commands.add('buildReduxStateWithServiceRespone', buildReduxStateWithServiceRespone);
index 5062f51..d9e64c0 100644 (file)
@@ -15,6 +15,7 @@
 
 // Import commands.js using ES2015 syntax:
 import './commands';
+import 'cypress-file-upload';
 import './steps/login.step';
 import './steps/fill.service.popup.step';
 import './steps/fill.vnf.popup.step';
@@ -36,12 +37,14 @@ import './steps/drawingBoard/drawingBoardModel.steps';
 import './steps/drawingBoard/drawingBoardTree.steps';
 import './steps/genericForm/genericFormAction.steps';
 import './steps/genericForm/popupViewport.step';
-import './steps/drawingBoard/drawingBoardHeader.steps';
 import './steps/drawingBoard/general.steps';
+import './steps/drawingBoard/drawingBoardRecreate.steps';
+import './steps/drawingBoard/drawingBoardHeader.steps';
 import './steps/general/clickOutside.step';
 import './steps/drawingBoard/drawingBoardComponentInfo.steps';
 import './steps/genericForm/checkPopover.step';
 
+
 // Alternatively you can use CommonJS syntax:
 // require('./commands')
 
index ae60361..807a3bc 100644 (file)
@@ -9,6 +9,7 @@ declare namespace Cypress {
     initActiveVPNs : typeof  initActiveVPNs;
     initGetAAISubDetails : typeof  initGetAAISubDetails;
     initAAIServices: typeof initAAIServices;
+    initGetModelByServiceType: typeof initGetModelByServiceType;
   }
 }
 
@@ -48,6 +49,19 @@ function initGetAAISubDetails(response? : JSON) : void {
   });
 }
 
+function initGetModelByServiceType(response? : JSON) : void {
+  cy.readFile('cypress/support/jsonBuilders/mocks/jsons/aaiSubDetails.json').then((res) => {
+    cy.server()
+      .route({
+        method: 'GET',
+        status: 200,
+        url: Cypress.config('baseUrl') + "/aai_get_models_by_service_type/**",
+        response: response ? response : res
+      }).as('aai-sub-details')
+  });
+}
+
+
 function initAlaCarteService(response? : JSON) : void {
   cy.readFile('cypress/support/jsonBuilders/mocks/jsons/a-la-carteService.json').then((res) => {
     cy.server()
@@ -156,6 +170,7 @@ Cypress.Commands.add('initSearchVNFMemebers', initSearchVNFMemebers);
 Cypress.Commands.add('initActiveNetworks', initActiveNetworks);
 Cypress.Commands.add('initActiveVPNs', initActiveVPNs);
 Cypress.Commands.add('initAAIServices', initAAIServices);
+Cypress.Commands.add('initGetModelByServiceType', initGetModelByServiceType);
 
 
 
diff --git a/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/aaiGetModelsByServiceType.json b/vid-webpack-master/cypress/support/jsonBuilders/mocks/jsons/aaiGetModelsByServiceType.json
new file mode 100644 (file)
index 0000000..2540650
--- /dev/null
@@ -0,0 +1,58 @@
+{
+  "inventory-response-item": [
+    {
+      "service-subscription": {
+        "service-type": "TYLER SILVIA",
+        "resource-version": "1494001841964"
+      },
+      "extra-properties": {},
+      "inventory-response-items": {
+        "inventory-response-item":[
+          {
+            "model-name": "RG_11-18_vccf_srvc",
+            "service-instance": {
+              "service-instance-id": "b9769e8f-70aa-4b05-8988-64044aa63498",
+              "service-instance-name": "TestCharlie",
+              "model-invariant-id": "4af418a9-c2f5-4fae-a577-b69d6341eee8",
+              "model-version-id": "745d1bf1-9ed1-413f-8111-f1e984ad63fb",
+              "resource-version": "1494002070115"
+            },
+            "extra-properties": {
+              "extra-property": [
+                {
+                  "property-name": "model-ver.model-description",
+                  "property-value": "Service for vccf"
+                },
+                {
+                  "property-name": "model-ver.model-version-id",
+                  "property-value": "745d1bf1-9ed1-413f-8111-f1e984ad63fb"
+                },
+                {
+                  "property-name": "model-ver.model-name",
+                  "property-value": "RG_11-18_vccf_srvc"
+                },
+                {
+                  "property-name": "model.model-type",
+                  "property-value": "service"
+                },
+                {
+                  "property-name": "model.model-invariant-id",
+                  "property-value": "4af418a9-c2f5-4fae-a577-b69d6341eee8"
+                },
+                {
+                  "property-name": "model.model-description"
+                },
+                {
+                  "property-name": "model-ver.model-version",
+                  "property-value": "1.0"
+                }
+              ]
+            }
+          }
+        ]
+      }
+    }
+  ]
+}
+
+
index 531bad3..d9602d1 100644 (file)
   "FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE": false,
   "FLAG_2002_VNF_PLATFORM_MULTI_SELECT" : true,
   "FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS": true,
-  "FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER": true,
   "FLAG_2004_INSTANTIATION_STATUS_FILTER": true,
   "FLAG_2004_INSTANTIATION_TEMPLATES_POPUP" : false,
   "FLAG_2002_UNLIMITED_MAX" : true,
-  "FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE": true
+  "FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE": true,
+  "FLAG_2006_VFM_SDNC_PRELOAD_FILES" : true,
+  "FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF": true
 }
index bc37b6b..847ebf0 100644 (file)
@@ -32,7 +32,7 @@
   "subscriberName":"SILVIA ROBBINS",
   "owningEntityName":"WayneHolland",
   "rollbackOnFailure":"true",
-  "testApi": "VNF_API",
+  "testApi": "GR_API",
   "isALaCarte":true,
   "action": "Create"
 }
diff --git a/vid-webpack-master/cypress/support/steps/drawingBoard/drawingBoardRecreate.steps.ts b/vid-webpack-master/cypress/support/steps/drawingBoard/drawingBoardRecreate.steps.ts
new file mode 100644 (file)
index 0000000..16f418b
--- /dev/null
@@ -0,0 +1,52 @@
+declare namespace Cypress {
+  interface Chainable {
+    loadDrawingBoardWithRecreateMode: typeof loadDrawingBoardWithRecreateMode ,
+    loadDrawingBoardWithRecreateModeNetwork: typeof loadDrawingBoardWithRecreateModeNetwork,
+    loadDrawingBoardWithRecreateModeInternal: typeof loadDrawingBoardWithRecreateModeInternal
+  }
+}
+
+function loadDrawingBoardWithRecreateMode(templateWithVnfSetup : any) {
+  cy.loadDrawingBoardWithRecreateModeInternal(
+    '../../' + templateWithVnfSetup.instanceTemplateFile,
+    templateWithVnfSetup.serviceModelId,
+    templateWithVnfSetup.serviceModelFile);
+}
+
+function loadDrawingBoardWithRecreateModeNetwork(templateWithNetworkSetup : any) {
+  cy.loadDrawingBoardWithRecreateModeInternal(
+    '../../' + templateWithNetworkSetup.instanceTemplateFile,
+    templateWithNetworkSetup.serviceModelId,
+    templateWithNetworkSetup.serviceModelFile);
+}
+
+function loadDrawingBoardWithRecreateModeInternal(instanceTemplate: string, serviceModelIdToLoad: any, serviceModel: string) {
+  const templateUuid = "46390edd-7100-46b2-9f18-419bd24fb60b";
+
+  const drawingBoardAction = `RECREATE`;
+  const templateTopologyEndpoint = "templateTopology";
+  cy.route(`**/rest/models/services/${serviceModelIdToLoad}`,
+    'fixture:' + serviceModel)
+    .as('serviceModel');
+
+  cy.route(`**/instantiationTemplates/${templateTopologyEndpoint}/${templateUuid}`,
+    'fixture:' + instanceTemplate)
+    .as('templateTopology');
+
+  // When...
+
+  cy.openIframe(`app/ui/#/servicePlanning/${drawingBoardAction}` +
+    `?jobId=${templateUuid}` +
+    `&serviceModelId=${serviceModelIdToLoad}`);
+
+  cy.wait('@serviceModel');
+  cy.wait('@templateTopology');
+}
+
+
+
+
+
+Cypress.Commands.add('loadDrawingBoardWithRecreateMode', loadDrawingBoardWithRecreateMode);
+Cypress.Commands.add('loadDrawingBoardWithRecreateModeNetwork', loadDrawingBoardWithRecreateModeNetwork);
+Cypress.Commands.add('loadDrawingBoardWithRecreateModeInternal', loadDrawingBoardWithRecreateModeInternal);
index 8d2bb8a..797fff0 100644 (file)
@@ -1,7 +1,10 @@
 declare namespace Cypress {
   interface Chainable {
     updateServiceShouldNotOverrideChild: typeof updateServiceShouldNotOverrideChild
-    openServiceContextMenu: typeof openServiceContextMenu
+    openServiceContextMenu: typeof openServiceContextMenu,
+    drawingBoardTreeClickOnContextMenuOptionByName : typeof  drawingBoardTreeClickOnContextMenuOptionByName,
+    nodeAction: typeof nodeAction,
+    editNode : typeof editNode
   }
 }
 
@@ -18,7 +21,6 @@ function updateServiceShouldNotOverrideChild() : void  {
           });
         });
     });
-
 }
 
 
@@ -26,5 +28,36 @@ function openServiceContextMenu() :  Chainable<any> {
  return cy.getElementByDataTestsId('openMenuBtn').click({force: true});
 }
 
+function nodeAction(dataTestId: string, action: string, index ?: number) {
+  return cy.drawingBoardTreeOpenContextMenuByElementDataTestId(dataTestId, index)
+    .drawingBoardTreeClickOnContextMenuOptionByName(action)
+}
+
+function drawingBoardTreeClickOnContextMenuOptionByName(optionName : string) : Chainable<any>  {
+  switch (optionName) {
+    case 'Duplicate':
+      return cy.getElementByDataTestsId('context-menu-duplicate').click({force : true});
+    case 'Remove':
+      return cy.getElementByDataTestsId('context-menu-remove').click({force : true});
+    case 'Edit':
+      return cy.getElementByDataTestsId('context-menu-edit').click({force : true});
+    case 'Delete':
+      return cy.getElementByDataTestsId('context-menu-delete').trigger('mouseover').click();
+    case 'Upgrade':
+      return cy.getElementByDataTestsId('context-menu-upgrade').trigger('mouseover').click();
+    case 'Undo Upgrade':
+      return cy.getElementByDataTestsId('context-menu-undoUpgrade').trigger('mouseover').click();
+    default:
+      return cy.getElementByDataTestsId('context-menu-duplicate').click({force : true});
+  }
+}
+
+function editNode(dataTestId: string, index ?: number) {
+  return cy.nodeAction(dataTestId, 'Edit', index);
+}
+
 Cypress.Commands.add('updateServiceShouldNotOverrideChild', updateServiceShouldNotOverrideChild);
 Cypress.Commands.add('openServiceContextMenu', openServiceContextMenu);
+Cypress.Commands.add('drawingBoardTreeClickOnContextMenuOptionByName', drawingBoardTreeClickOnContextMenuOptionByName);
+Cypress.Commands.add('nodeAction', nodeAction);
+Cypress.Commands.add('editNode', editNode);
index b87e773..cfb8a05 100644 (file)
@@ -34,7 +34,7 @@ function addMacroVfModule(vnfName: string, vfModuleName: string, instanceName: s
 }
 
 function addALaCarteVfModule(vnfName: string, vfModuleName: string, instanceName: string, lcpRegion: string, legacyRegion: string,
-                     tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean): Chainable<any> {
+                     tenant: string, rollback: boolean, sdncPreLoad: boolean, deleteVgName: boolean, flag: boolean): Chainable<any> {
   return cy.getElementByDataTestsId('node-' + vnfName).click({force: true}).then(() => {
     cy.getElementByDataTestsId('node-' + vfModuleName + '-add-btn').click({force: true}).then(() => {
       cy.getElementByDataTestsId('instanceName').clear().type(instanceName, {force: true}).then(() => {
@@ -42,11 +42,13 @@ function addALaCarteVfModule(vnfName: string, vfModuleName: string, instanceName
           cy.getElementByDataTestsId('volumeGroupName').clear();
         }
       }).then(() => {
-        cy.selectDropdownOptionByText('lcpRegion', lcpRegion);
-        if (legacyRegion) {
-          cy.typeToInput("lcpRegionText", legacyRegion);
+        if(!flag) {
+          cy.selectDropdownOptionByText('lcpRegion', lcpRegion);
+          if (legacyRegion) {
+            cy.typeToInput("lcpRegionText", legacyRegion);
+          }
+          cy.selectDropdownOptionByText('tenant', tenant);
         }
-        cy.selectDropdownOptionByText('tenant', tenant);
         cy.selectDropdownOptionByText('rollback', String(rollback));
         if (sdncPreLoad) {
           cy.getElementByDataTestsId('sdncPreLoad').check();
diff --git a/vid-webpack-master/cypress/support/uploadFiles/sdncPreLoadFileExample.json b/vid-webpack-master/cypress/support/uploadFiles/sdncPreLoadFileExample.json
new file mode 100644 (file)
index 0000000..c317c41
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "comment" : "invalid file, just for upload mock file"
+}
index da6aa60..8ce197f 100644 (file)
@@ -16,6 +16,7 @@
     "cypress": "3.6.1",
     "typescript": "3.1.6",
     "rxjs": "^6.3.3",
-    "rxjs-compat": "^6.3.3"
+    "rxjs-compat": "^6.3.3",
+    "cypress-file-upload": "^3.5.3"
   }
 }
old mode 100644 (file)
new mode 100755 (executable)
index ee04de1..fdaf3e3
   "private": true,
   "dependencies": {
     "@angular-redux/store": "9.0.0",
-    "@angular/animations": "7.1.4",
+    "@angular/animations": "8.2.14",
     "@angular/cdk": "7.2.2",
-    "@angular/common": "7.1.4",
-    "@angular/compiler": "7.1.4",
-    "@angular/core": "7.1.4",
-    "@angular/forms": "7.1.4",
-    "@angular/http": "7.1.4",
+    "@angular/common": "8.2.14",
+    "@angular/compiler": "8.2.14",
+    "@angular/core": "8.2.14",
+    "@angular/forms": "8.2.14",
     "@angular/material": "7.2.2",
-    "@angular/platform-browser": "7.1.4",
-    "@angular/platform-browser-dynamic": "7.1.4",
-    "@angular/platform-server": "7.1.4",
-    "@angular/router": "7.1.4",
+    "@angular/platform-browser": "8.2.14",
+    "@angular/platform-browser-dynamic": "8.2.14",
+    "@angular/platform-server": "8.2.14",
+    "@angular/router": "8.2.14",
     "@harmowatch/ngx-redux-core": "0.2.2",
-    "@nicky-lenaers/ngx-scroll-to": "^0.6.1",
+    "@nicky-lenaers/ngx-scroll-to": "3.0.1",
     "@turf/turf": "5.1.6",
     "@types/lodash": "4.14.121",
     "angular-svg-icon": "5.0.0",
-    "angular-tree-component": "8.4.0",
+    "angular-tree-component": "8.5.2",
     "angular2-datatable": "0.6.0",
     "angular2-multiselect-dropdown": "2.5.0",
     "angular5-csv": "^0.2.10",
     "moment": "^2.24.0",
     "ng-multiselect-dropdown": "0.1.3",
     "ng2-bootstrap-modal": "1.0.1",
+    "ng2-file-upload": "^1.4.0",
     "ngx-bootstrap": "^2.0.2",
     "ngx-contextmenu": "^5.1.1",
     "ngx-datatable": "1.0.3",
     "ngx-moment": "^2.0.0-rc.0",
     "ngx-tooltip": "0.0.9",
+    "node-sass": "^4.13.0",
     "npm": "^6.4.1",
     "redux": "4.0.1",
     "redux-observable": "^1.0.0",
     "rxjs-compat": "^6.3.3",
     "slnodejs": "^2.1.124",
     "tslib": "1.9.x",
-    "zone.js": "^0.8.26"
+    "zone.js": "~0.9.1"
   },
   "devDependencies": {
     "@angular-builders/jest": "7.3.1",
-    "@angular-devkit/build-angular": "0.13.1",
-    "@angular/cli": "7.3.1",
-    "@angular/compiler-cli": "7.2.5",
-    "@angular/language-service": "7.2.5",
+    "@angular-devkit/build-angular": "~0.803.21",
+    "@angular/cli": "8.3.21",
+    "@angular/compiler-cli": "8.2.14",
+    "@angular/language-service": "8.2.14",
     "@babel/preset-env": "7.3.1",
     "@bahmutov/add-typescript-to-cypress": "2.0.0",
     "@types/chai": "4.1.7",
     "@types/node": "^10.12.18",
     "angular2-template-loader": "0.6.2",
     "babel-jest": "24.1.0",
-    "codelyzer": "4.5.0",
+    "blueimp-file-upload": "^10.7.0",
+    "codelyzer": "^5.0.1",
     "cypress": "3.6.1",
+    "cypress-file-upload": "^3.5.3",
     "hammerjs": "2.0.8",
     "husky": "^1.3.1",
     "istanbul-reports": "2.1.1",
     "jest-sonar-reporter": "2.0.0",
     "ngx-wallaby-jest": "0.0.1",
     "npm-run-all": "^4.1.5",
-    "onap-ui-angular": "5.2.4",
+    "onap-ui-angular": "5.2.7",
     "onap-ui-common": "1.0.105",
     "prettier": "1.16.4",
     "pretty-quick": "^1.10.0",
+    "redux-observable-es6-compat": "^1.2.1",
     "ts-mockito": "2.3.1",
     "ts-node": "~5.0.1",
     "tslint": "^5.12.0",
-    "typescript": "3.1.6",
+    "typescript": "3.5.3",
     "wallaby-webpack": "^3.9.11",
     "webpack": "^4.28.2"
   },
index f84a485..bfca33e 100644 (file)
@@ -9,7 +9,7 @@
       inherit from a parent maven module. -->
   <groupId>org.onap.vid</groupId>
   <artifactId>vid-webpack-master</artifactId>
-  <version>6.0.0-SNAPSHOT</version>
+  <version>6.0.3-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>VID UI</name>
   <description>VID UI</description>
                 </goals>
                 <configuration>
                   <!-- See https://nodejs.org/en/download/ for latest node and npm (lts) versions -->
-                  <nodeVersion>v8.9.4</nodeVersion>
-                  <npmVersion>5.6.0</npmVersion>
+                  <nodeVersion>v10.15.3</nodeVersion>
+                  <npmVersion>6.9.0</npmVersion>
                 </configuration>
               </execution>
 
index 25d1703..7e59f17 100644 (file)
@@ -36,6 +36,8 @@ import {ComponentInfoComponent} from './service-planning/component-info/componen
 import {ComponentInfoService} from "./service-planning/component-info/component-info.service";
 import {NetworkStepService} from "./service-planning/objectsToTree/models/vrf/vrfModal/networkStep/network.step.service";
 import {VpnStepService} from "./service-planning/objectsToTree/models/vrf/vrfModal/vpnStep/vpn.step.service";
+import {ModalModule} from "onap-ui-angular/dist/modals/modal.module";
+import {ModalService} from "../shared/components/customModal/services/modal.service";
 
 
 @NgModule({
@@ -48,7 +50,8 @@ import {VpnStepService} from "./service-planning/objectsToTree/models/vrf/vrfMod
     CommonModule,
     SdcUiComponentsModule,
     SharedModule.forRoot(),
-    FeatureFlagModule.forRoot()],
+    FeatureFlagModule.forRoot(),
+    ModalModule],
   providers: [
     AaiService,
     ObjectToTreeService,
@@ -64,7 +67,7 @@ import {VpnStepService} from "./service-planning/objectsToTree/models/vrf/vrfMod
     DynamicInputsService,
     InstanceTreeGenerator,
     SharedTreeService,
-    SdcUiServices.ModalService,
+    ModalService,
     SdcUiServices.LoaderService,
     CreateDynamicComponentService,
     ComponentInfoService,
@@ -83,7 +86,7 @@ import {VpnStepService} from "./service-planning/objectsToTree/models/vrf/vrfMod
     SearchComponent,
     ComponentInfoComponent],
   entryComponents: [DuplicateVnfComponent],
-  exports: [AvailableModelsTreeComponent, DrawingBoardTreeComponent, DrawingBoardHeader, TreeNodeHeaderPropertiesComponent, SearchComponent]
+  exports: [AvailableModelsTreeComponent, DrawingBoardTreeComponent, DrawingBoardHeader, TreeNodeHeaderPropertiesComponent, SearchComponent, DuplicateVnfComponent]
 })
 
 export class DrawingBoardModule {
index 7864808..d309f21 100644 (file)
               <span [attr.data-tests-id]="'numberButton'">{{node.data.getNodeCount(node, this.serviceModelId)}}</span>
             </span>
             <span class="icon-v" *ngIf="node?.data?.showNodeIcons(node, serviceModelId)?.vIcon">
-                <svg-icon
+                <custom-icon
                   [mode]="'secondary'"
                   [name]="'maximum'">
-              </svg-icon>
+              </custom-icon>
             </span>
             <span class="icon-plus" *ngIf="_store.getState().service.serviceInstance[serviceModelId].action !== 'Delete' && node?.data?.showNodeIcons(node, serviceModelId)?.addIcon">
               <span tooltip="Add" [attr.data-tests-id]="'node-'+node.data.name+'-add-btn'" (click)="onClickAdd(node, serviceModelId)">
index 13147b7..2e04f53 100644 (file)
@@ -88,7 +88,7 @@ export class AvailableModelsTreeComponent {
 
   @Output()
   highlightInstances: EventEmitter<number> = new EventEmitter<number>();
-  @ViewChild('tree') tree: TreeComponent;
+  @ViewChild('tree', {static: false}) tree: TreeComponent;
 
   nodes = [];
   service = {name: ''};
@@ -134,7 +134,13 @@ export class AvailableModelsTreeComponent {
     this.highlightInstances.emit(node.data.modelUniqueId);
     if (FeatureFlagsService.getFlagState(Features.FLAG_1906_COMPONENT_INFO, this.store)) {
       const serviceHierarchy = this._store.getState().service.serviceHierarchy[this.serviceModelId];
-      const model = node.data.getModel(node.data.name, node.data, serviceHierarchy);
+
+      const instanceModel = this._sharedTreeService.modelByIdentifiers(
+        serviceHierarchy, node.data.modelTypeName,
+        this._sharedTreeService.modelUniqueNameOrId(node.data), node.data.name
+      );
+
+      const model = node.data.getModel(instanceModel);
       const modelInfoItems  = node.data.getInfo(model, null);
       const componentInfoModel :ComponentInfoModel = this._sharedTreeService.addGeneralInfoItems(modelInfoItems, node.data.componentInfoType, model, null);
       ComponentInfoService.triggerComponentInfoChange.next(componentInfoModel);
index 4abc203..6a101d3 100644 (file)
@@ -14,6 +14,7 @@ describe('Available Models Tree Service', () => {
   let injector;
   let service: AvailableModelsTreeService;
   let httpMock: HttpTestingController;
+  let sharedTreeService: SharedTreeService;
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -27,6 +28,7 @@ describe('Available Models Tree Service', () => {
       injector = getTestBed();
       service = injector.get(AvailableModelsTreeService);
       httpMock = injector.get(HttpTestingController);
+      sharedTreeService = injector.get(SharedTreeService);
   })().then(done).catch(done.fail));
 
 
@@ -47,7 +49,6 @@ describe('Available Models Tree Service', () => {
 
 
   describe('#shouldOpenModalDialogOnAddInstance', () => {
-    let serviceHierarchy = getServiceServiceHierarchy();
 
     test('should open popup on add instance', () => {
       // add vnf should return true
@@ -99,6 +100,8 @@ describe('Available Models Tree Service', () => {
       "isEcompGeneratedNaming": false,
       "typeName": "VRF",
       "componentInfoType": "VRF",
+      "data": {
+      },
       "getModel" : ()=>{
         return  {
           min : 1
@@ -108,6 +111,9 @@ describe('Available Models Tree Service', () => {
 
 
     const serviceStore = {
+      "serviceHierarchy": {
+        "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc": {}
+      },
       "serviceInstance": {
         "4117a0b6-e234-467d-b5b9-fe2f68c8b0fc": {
           "action": "Create",
@@ -158,7 +164,7 @@ describe('Available Models Tree Service', () => {
                   "physicalName": "sriovnet0",
                   "instanceId": "46fcb25a-e7ba-4d96-99ba-3bb6eae6aba7",
                   "serviceName": "LPPVPN",
-                  "serv§iceUUID": "VPN1271",
+                  "serviceUUID": "VPN1271",
                   "tenantName": "ecomp_ispt",
                   "lcpCloudRegionId": "USA,EMEA",
                   "modelInfo": {
@@ -221,6 +227,8 @@ describe('Available Models Tree Service', () => {
       }
     };
 
+    spyOn(sharedTreeService, 'modelByIdentifiers').and.returnValue({});
+
     const serviceModelId :string = '4117a0b6-e234-467d-b5b9-fe2f68c8b0fc';
 
     let result: boolean = service.shouldOpenVRFModal(nodes,  serviceModelId, serviceStore);
@@ -235,344 +243,4 @@ describe('Available Models Tree Service', () => {
 
   });
 
-  function getServiceServiceHierarchy() {
-    return JSON.parse(JSON.stringify(
-      {
-        '6e59c5de-f052-46fa-aa7e-2fca9d674c44': {
-          'service': {
-            'uuid': '6e59c5de-f052-46fa-aa7e-2fca9d674c44',
-            'invariantUuid': 'e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0',
-            'name': 'ComplexService',
-            'version': '1.0',
-            'toscaModelURL': null,
-            'category': 'Emanuel',
-            'serviceType': '',
-            'serviceRole': '',
-            'description': 'ComplexService',
-            'serviceEcompNaming': 'true',
-            'instantiationType': 'Macro',
-            'inputs': {}
-          },
-          'vnfs': {
-            'VF_vGeraldine 0': {
-              'uuid': 'd6557200-ecf2-4641-8094-5393ae3aae60',
-              'invariantUuid': '4160458e-f648-4b30-a176-43881ffffe9e',
-              'description': 'VSP_vGeraldine',
-              'name': 'VF_vGeraldine',
-              'version': '2.0',
-              'customizationUuid': '91415b44-753d-494c-926a-456a9172bbb9',
-              'inputs': {},
-              'commands': {},
-              'properties': {
-                'max_instances': '3',
-                'min_instances': '1',
-                'gpb2_Internal2_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-ipv6-egress_src_start_port': '0',
-                'sctp-a-ipv6-egress_rule_application': 'any',
-                'Internal2_allow_transit': 'true',
-                'sctp-b-IPv6_ethertype': 'IPv6',
-                'sctp-a-egress_rule_application': 'any',
-                'sctp-b-ingress_action': 'pass',
-                'sctp-b-ingress_rule_protocol': 'icmp',
-                'ncb2_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-ipv6-ingress-src_start_port': '0.0',
-                'ncb1_Internal2_mac': '00:11:22:EF:AC:DF',
-                'fsb_volume_size_0': '320.0',
-                'sctp-b-egress_src_addresses': 'local',
-                'sctp-a-ipv6-ingress_ethertype': 'IPv4',
-                'sctp-a-ipv6-ingress-dst_start_port': '0',
-                'sctp-b-ipv6-ingress_rule_application': 'any',
-                'domain_name': 'default-domain',
-                'sctp-a-ingress_rule_protocol': 'icmp',
-                'sctp-b-egress-src_start_port': '0.0',
-                'sctp-a-egress_src_addresses': 'local',
-                'sctp-b-display_name': 'epc-sctp-b-ipv4v6-sec-group',
-                'sctp-a-egress-src_start_port': '0.0',
-                'sctp-a-ingress_ethertype': 'IPv4',
-                'sctp-b-ipv6-ingress-dst_end_port': '65535',
-                'sctp-b-dst_subnet_prefix_v6': '::',
-                'nf_naming': '{ecomp_generated_naming=true}',
-                'sctp-a-ipv6-ingress_src_subnet_prefix': '0.0.0.0',
-                'sctp-b-egress-dst_start_port': '0.0',
-                'ncb_flavor_name': 'nv.c20r64d1',
-                'gpb1_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-egress_dst_subnet_prefix_len': '0.0',
-                'Internal2_net_cidr': '10.0.0.10',
-                'sctp-a-ingress-dst_start_port': '0.0',
-                'sctp-a-egress-dst_start_port': '0.0',
-                'fsb1_Internal2_mac': '00:11:22:EF:AC:DF',
-                'sctp-a-egress_ethertype': 'IPv4',
-                'vlc_st_service_mode': 'in-network-nat',
-                'sctp-a-ipv6-egress_ethertype': 'IPv4',
-                'sctp-a-egress-src_end_port': '65535.0',
-                'sctp-b-ipv6-egress_rule_application': 'any',
-                'sctp-b-egress_action': 'pass',
-                'sctp-a-ingress-src_subnet_prefix_len': '0.0',
-                'sctp-b-ipv6-ingress-src_end_port': '65535.0',
-                'sctp-b-name': 'epc-sctp-b-ipv4v6-sec-group',
-                'fsb2_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-a-ipv6-ingress-src_start_port': '0.0',
-                'sctp-b-ipv6-egress_ethertype': 'IPv4',
-                'Internal1_net_cidr': '10.0.0.10',
-                'sctp-a-egress_dst_subnet_prefix': '0.0.0.0',
-                'fsb_flavor_name': 'nv.c20r64d1',
-                'sctp_rule_protocol': '132',
-                'sctp-b-ipv6-ingress_src_subnet_prefix_len': '0',
-                'sctp-a-ipv6-ingress_rule_application': 'any',
-                'sctp-a-IPv6_ethertype': 'IPv6',
-                'vlc2_Internal1_mac': '00:11:22:EF:AC:DF',
-                'vlc_st_virtualization_type': 'virtual-machine',
-                'sctp-b-ingress-dst_start_port': '0.0',
-                'sctp-b-ingress-dst_end_port': '65535.0',
-                'sctp-a-ipv6-ingress-src_end_port': '65535.0',
-                'sctp-a-display_name': 'epc-sctp-a-ipv4v6-sec-group',
-                'sctp-b-ingress_rule_application': 'any',
-                'int2_sec_group_name': 'int2-sec-group',
-                'vlc_flavor_name': 'nd.c16r64d1',
-                'sctp-b-ipv6-egress_src_addresses': 'local',
-                'vlc_st_interface_type_int1': 'other1',
-                'sctp-b-egress-src_end_port': '65535.0',
-                'sctp-a-ipv6-egress-dst_start_port': '0',
-                'vlc_st_interface_type_int2': 'other2',
-                'sctp-a-ipv6-egress_rule_protocol': 'any',
-                'Internal2_shared': 'false',
-                'sctp-a-ipv6-egress_dst_subnet_prefix_len': '0',
-                'Internal2_rpf': 'disable',
-                'vlc1_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-ipv6-egress_src_end_port': '65535',
-                'sctp-a-ipv6-egress_src_addresses': 'local',
-                'sctp-a-ingress-dst_end_port': '65535.0',
-                'sctp-a-ipv6-egress_src_end_port': '65535',
-                'Internal1_forwarding_mode': 'l2',
-                'Internal2_dhcp': 'false',
-                'sctp-a-dst_subnet_prefix_v6': '::',
-                'pxe_image_name': 'MME_PXE-Boot_16ACP04_GA.qcow2',
-                'vlc_st_interface_type_gtp': 'other0',
-                'ncb1_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-src_subnet_prefix_v6': '::',
-                'sctp-a-egress_dst_subnet_prefix_len': '0.0',
-                'int1_sec_group_name': 'int1-sec-group',
-                'Internal1_dhcp': 'false',
-                'sctp-a-ipv6-egress_dst_end_port': '65535',
-                'Internal2_forwarding_mode': 'l2',
-                'fsb2_Internal2_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-egress_dst_subnet_prefix': '0.0.0.0',
-                'Internal1_net_cidr_len': '17',
-                'gpb2_Internal1_mac': '00:11:22:EF:AC:DF',
-                'sctp-b-ingress-src_subnet_prefix_len': '0.0',
-                'sctp-a-ingress_dst_addresses': 'local',
-                'sctp-a-egress_action': 'pass',
-                'fsb_volume_type_0': 'SF-Default-SSD',
-                'ncb2_Internal2_mac': '00:11:22:EF:AC:DF',
-                'vlc_st_interface_type_sctp_a': 'left',
-                'vlc_st_interface_type_sctp_b': 'right',
-                'sctp-a-src_subnet_prefix_v6': '::',
-                'vlc_st_version': '2',
-                'sctp-b-egress_ethertype': 'IPv4',
-                'sctp-a-ingress_rule_application': 'any',
-                'gpb1_Internal2_mac': '00:11:22:EF:AC:DF',
-                'instance_ip_family_v6': 'v6',
-                'sctp-a-ipv6-egress_src_start_port': '0',
-                'sctp-b-ingress-src_start_port': '0.0',
-                'sctp-b-ingress_dst_addresses': 'local',
-                'fsb1_Internal1_mac': '00:11:22:EF:AC:DF',
-                'vlc_st_interface_type_oam': 'management',
-                'multi_stage_design': 'false',
-                'oam_sec_group_name': 'oam-sec-group',
-                'Internal2_net_gateway': '10.0.0.10',
-                'sctp-a-ipv6-ingress-dst_end_port': '65535',
-                'sctp-b-ipv6-egress-dst_start_port': '0',
-                'Internal1_net_gateway': '10.0.0.10',
-                'sctp-b-ipv6-egress_rule_protocol': 'any',
-                'gtp_sec_group_name': 'gtp-sec-group',
-                'sctp-a-ipv6-egress_dst_subnet_prefix': '0.0.0.0',
-                'sctp-b-ipv6-egress_dst_subnet_prefix_len': '0',
-                'sctp-a-ipv6-ingress_dst_addresses': 'local',
-                'sctp-a-egress_rule_protocol': 'icmp',
-                'sctp-b-ipv6-egress_action': 'pass',
-                'sctp-a-ipv6-egress_action': 'pass',
-                'Internal1_shared': 'false',
-                'sctp-b-ipv6-ingress_rule_protocol': 'any',
-                'Internal2_net_cidr_len': '17',
-                'sctp-a-name': 'epc-sctp-a-ipv4v6-sec-group',
-                'sctp-a-ingress-src_end_port': '65535.0',
-                'sctp-b-ipv6-ingress_src_subnet_prefix': '0.0.0.0',
-                'sctp-a-egress-dst_end_port': '65535.0',
-                'sctp-a-ingress_action': 'pass',
-                'sctp-b-egress_rule_protocol': 'icmp',
-                'sctp-b-ipv6-ingress_action': 'pass',
-                'vlc_st_service_type': 'firewall',
-                'sctp-b-ipv6-egress_dst_end_port': '65535',
-                'sctp-b-ipv6-ingress-dst_start_port': '0',
-                'vlc2_Internal2_mac': '00:11:22:EF:AC:DF',
-                'vlc_st_availability_zone': 'true',
-                'fsb_volume_image_name_1': 'MME_FSB2_16ACP04_GA.qcow2',
-                'sctp-b-ingress-src_subnet_prefix': '0.0.0.0',
-                'sctp-a-ipv6-ingress_src_subnet_prefix_len': '0',
-                'Internal1_allow_transit': 'true',
-                'gpb_flavor_name': 'nv.c20r64d1',
-                'availability_zone_max_count': '1',
-                'fsb_volume_image_name_0': 'MME_FSB1_16ACP04_GA.qcow2',
-                'sctp-b-ipv6-ingress_dst_addresses': 'local',
-                'sctp-b-ipv6-egress_dst_subnet_prefix': '0.0.0.0',
-                'sctp-b-ipv6-ingress_ethertype': 'IPv4',
-                'vlc1_Internal2_mac': '00:11:22:EF:AC:DF',
-                'sctp-a-ingress-src_subnet_prefix': '0.0.0.0',
-                'sctp-a-ipv6-ingress_action': 'pass',
-                'Internal1_rpf': 'disable',
-                'sctp-b-ingress_ethertype': 'IPv4',
-                'sctp-b-egress_rule_application': 'any',
-                'sctp-b-ingress-src_end_port': '65535.0',
-                'sctp-a-ipv6-ingress_rule_protocol': 'any',
-                'sctp-a-ingress-src_start_port': '0.0',
-                'sctp-b-egress-dst_end_port': '65535.0'
-              },
-              'type': 'VF',
-              'modelCustomizationName': 'VF_vGeraldine 0',
-              'vfModules': {
-                'vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1': {
-                  'uuid': '522159d5-d6e0-4c2a-aa44-5a542a12a830',
-                  'invariantUuid': '98a7c88b-b577-476a-90e4-e25a5871e02b',
-                  'customizationUuid': '55b1be94-671a-403e-a26c-667e9c47d091',
-                  'description': null,
-                  'name': 'VfVgeraldine..vflorence_vlc..module-1',
-                  'version': '2',
-                  'modelCustomizationName': 'VfVgeraldine..vflorence_vlc..module-1',
-                  'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0},
-                  'commands': {},
-                  'volumeGroupAllowed': false
-                },
-                'vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2': {
-                  'uuid': '41708296-e443-4c71-953f-d9a010f059e1',
-                  'invariantUuid': '1cca90b8-3490-495e-87da-3f3e4c57d5b9',
-                  'customizationUuid': '6add59e0-7fe1-4bc4-af48-f8812422ae7c',
-                  'description': null,
-                  'name': 'VfVgeraldine..vflorence_gpb..module-2',
-                  'version': '2',
-                  'modelCustomizationName': 'VfVgeraldine..vflorence_gpb..module-2',
-                  'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0},
-                  'commands': {},
-                  'volumeGroupAllowed': false
-                },
-                'vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0': {
-                  'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87',
-                  'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d',
-                  'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861',
-                  'description': null,
-                  'name': 'VfVgeraldine..base_vflorence..module-0',
-                  'version': '2',
-                  'modelCustomizationName': 'VfVgeraldine..base_vflorence..module-0',
-                  'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1},
-                  'commands': {},
-                  'volumeGroupAllowed': true
-                }
-              },
-              'volumeGroups': {
-                'vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0': {
-                  'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87',
-                  'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d',
-                  'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861',
-                  'description': null,
-                  'name': 'VfVgeraldine..base_vflorence..module-0',
-                  'version': '2',
-                  'modelCustomizationName': 'VfVgeraldine..base_vflorence..module-0',
-                  'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1}
-                }
-              }
-            }
-          },
-          'networks': {
-            'ExtVL 0': {
-              'uuid': 'ddc3f20c-08b5-40fd-af72-c6d14636b986',
-              'invariantUuid': '379f816b-a7aa-422f-be30-17114ff50b7c',
-              'description': 'ECOMP generic virtual link (network) base type for all other service-level and global networks',
-              'name': 'ExtVL',
-              'version': '37.0',
-              'customizationUuid': '94fdd893-4a36-4d70-b16a-ec29c54c184f',
-              'inputs': {},
-              'commands': {},
-              'properties': {
-                'network_assignments': '{is_external_network=false, ipv4_subnet_default_assignment={min_subnets_count=1}, ecomp_generated_network_assignment=false, ipv6_subnet_default_assignment={min_subnets_count=1}}',
-                'exVL_naming': '{ecomp_generated_naming=true}',
-                'network_flows': '{is_network_policy=false, is_bound_to_vpn=false}',
-                'network_homing': '{ecomp_selected_instance_node_target=false}'
-              },
-              'type': 'VL',
-              'modelCustomizationName': 'ExtVL 0'
-            }
-          },
-          'configurations': {
-            'Port Mirroring Configuration By Policy 0': {
-              'uuid': 'b4398538-e89d-4f13-b33d-ca323434ba50',
-              'invariantUuid': '6ef0ca40-f366-4897-951f-abd65d25f6f7',
-              'description': 'A port mirroring configuration by policy object',
-              'name': 'Port Mirroring Configuration By Policy',
-              'version': '27.0',
-              'customizationUuid': '3c3b7b8d-8669-4b3b-8664-61970041fad2',
-              'inputs': {},
-              'commands': {},
-              'properties': {},
-              'type': 'Configuration',
-              'modelCustomizationName': 'Port Mirroring Configuration By Policy 0',
-              'sourceNodes': [],
-              'collectorNodes': null,
-              'configurationByPolicy': false
-            }
-          },
-          'serviceProxies': {},
-          'vfModules': {
-            'vf_vgeraldine0..VfVgeraldine..vflorence_vlc..module-1': {
-              'uuid': '522159d5-d6e0-4c2a-aa44-5a542a12a830',
-              'invariantUuid': '98a7c88b-b577-476a-90e4-e25a5871e02b',
-              'customizationUuid': '55b1be94-671a-403e-a26c-667e9c47d091',
-              'description': null,
-              'name': 'VfVgeraldine..vflorence_vlc..module-1',
-              'version': '2',
-              'modelCustomizationName': 'VfVgeraldine..vflorence_vlc..module-1',
-              'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0},
-              'commands': {},
-              'volumeGroupAllowed': false
-            },
-            'vf_vgeraldine0..VfVgeraldine..vflorence_gpb..module-2': {
-              'uuid': '41708296-e443-4c71-953f-d9a010f059e1',
-              'invariantUuid': '1cca90b8-3490-495e-87da-3f3e4c57d5b9',
-              'customizationUuid': '6add59e0-7fe1-4bc4-af48-f8812422ae7c',
-              'description': null,
-              'name': 'VfVgeraldine..vflorence_gpb..module-2',
-              'version': '2',
-              'modelCustomizationName': 'VfVgeraldine..vflorence_gpb..module-2',
-              'properties': {'minCountInstances': 0, 'maxCountInstances': null, 'initialCount': 0},
-              'commands': {},
-              'volumeGroupAllowed': false
-            },
-            'vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0': {
-              'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87',
-              'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d',
-              'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861',
-              'description': null,
-              'name': 'VfVgeraldine..base_vflorence..module-0',
-              'version': '2',
-              'modelCustomizationName': 'VfVgeraldine..base_vflorence..module-0',
-              'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1},
-              'commands': {},
-              'volumeGroupAllowed': true
-            }
-          },
-          'volumeGroups': {
-            'vf_vgeraldine0..VfVgeraldine..base_vflorence..module-0': {
-              'uuid': 'a27f5cfc-7f12-4f99-af08-0af9c3885c87',
-              'invariantUuid': 'a6f9e51a-2b35-416a-ae15-15e58d61f36d',
-              'customizationUuid': 'f8c040f1-7e51-4a11-aca8-acf256cfd861',
-              'description': null,
-              'name': 'VfVgeraldine..base_vflorence..module-0',
-              'version': '2',
-              'modelCustomizationName': 'VfVgeraldine..base_vflorence..module-0',
-              'properties': {'minCountInstances': 1, 'maxCountInstances': 1, 'initialCount': 1}
-            }
-          },
-          'pnfs': {}
-        }
-      }
-    ));
-  }
 });
index c9a89cf..56d708b 100644 (file)
@@ -77,7 +77,13 @@ export class AvailableModelsTreeService {
   shouldOpenVRFModal(nodes, serviceModelId: string , service)  {
     for(const node of nodes){
       if(node.type === 'VRF' && service.serviceInstance[serviceModelId].existingVRFCounterMap && !service.serviceInstance[serviceModelId].existingVRFCounterMap[node.modelUniqueId]){
-        const vrfModel : VrfModel = node.getModel(node.name, node, service.serviceInstance[serviceModelId]);
+        const serviceHierarchy = service.serviceHierarchy[serviceModelId];
+
+        const instanceModel = this._sharedTreeService.modelByIdentifiers(
+          serviceHierarchy, node.modelTypeName, node.modelCustomizationId, node.name
+        );
+
+        const vrfModel : VrfModel = node.getModel(instanceModel);
         const vrfCounter : number = service.serviceInstance[serviceModelId].existingVRFCounterMap[node.modelUniqueId];
         console.log('vrfCounter', vrfCounter);
         if(vrfModel.min > 0 && (_.isNil(vrfCounter) || vrfCounter === 0)){
index 7a18bce..2c04678 100644 (file)
@@ -2,12 +2,12 @@
   <div class="left-header">
     <span class="vid-logo-small"></span>
     <span class="icon-back">
-      <svg-icon
+      <custom-icon
         (click)="closePage()"
         [testId]="'backBtn'"
         [size]="'large'"
         [name]="'navigation-arrow-back'">
-      </svg-icon>
+      </custom-icon>
     </span>
 
     <div class="header-col middleDetails" style="padding-top: 7px;padding-left: 13px;line-height: 100%;" *ngIf="isServiceFailed">
         <ng-template *ngIf="mode !== 'CREATE'" contextMenuItem
                      (execute)="drawingBoardHeaderService.showAuditInfo(serviceModelId)">
           <div  [attr.data-tests-id]="'context-menu-header-audit-item'" style="float: left;margin-top: 8px;">
-                  <svg-icon
+                  <custom-icon
                     [ngClass]="'eye-o'"
                     class="eye-o"
                     [size]="'small'"
                     [name]="'eye-o'">
-                </svg-icon></div>
+                </custom-icon></div>
                 <div style="padding-left: 12px;">Show Audit Info</div>
         </ng-template>
         <ng-template *ngIf="drawingBoardHeaderService?.showResumeService(serviceModelId)" contextMenuItem
index 8228f95..395b5f3 100644 (file)
@@ -80,7 +80,7 @@ export class DrawingBoardHeader {
   }
 
 
-  @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
+  @ViewChild(ContextMenuComponent, {static: false}) public contextMenu: ContextMenuComponent;
 
   editViewEdit(): void {
      window.parent.location.assign(this._drawingBoardHeaderService.generateOldViewEditPath());
index 96e5017..2daaaaf 100644 (file)
@@ -1,9 +1,7 @@
 import {Injectable} from "@angular/core";
 import {NgRedux} from "@angular-redux/store";
 import {AppState} from "../../../../shared/store/reducers";
-import {DragAndDropModel} from "./dragAndDrop.model";
 import {FeatureFlagsService, Features} from "../../../../shared/services/featureFlag/feature-flags.service";
-import * as _ from 'lodash';
 
 @Injectable()
 export class DragAndDropService {
index 4ad1b06..1a42db4 100644 (file)
@@ -13,7 +13,6 @@ import {DrawingBoardTreeService, TreeNodeContextMenuModel} from "./drawing-board
 import {NetworkPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/network/network.popup.service";
 import {VfModulePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service";
 import {VnfPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service";
-import {SdcUiServices} from "onap-ui-angular";
 import {HighlightPipe} from "../../../shared/pipes/highlight/highlight-filter.pipe";
 import {VnfGroupPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service";
 import {ObjectToInstanceTreeService} from "../objectsToTree/objectToInstanceTree/objectToInstanceTree.service";
@@ -29,6 +28,7 @@ import {ComponentInfoModel} from "../component-info/component-info-model";
 import {ObjectToModelTreeService} from "../objectsToTree/objectToModelTree/objectToModelTree.service";
 import {DrawingBoardModes} from "../drawing-board.modes";
 import {ServiceInstanceActions} from "../../../shared/models/serviceInstanceActions";
+import {ModalService} from "../../../shared/components/customModal/services/modal.service";
 
 @Component({
   selector: 'drawing-board-tree',
@@ -52,7 +52,7 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit {
   static triggerDeleteActionService: Subject<string> = new Subject<string>();
   static triggerUndoDeleteActionService: Subject<string> = new Subject<string>();
   static triggerreCalculateIsDirty: Subject<string> = new Subject<string>();
-  @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
+  @ViewChild(ContextMenuComponent, {static: false}) public contextMenu: ContextMenuComponent;
 
   constructor(private _contextMenuService: ContextMenuService,
               private _iframeService: IframeService,
@@ -60,7 +60,7 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit {
               private store: NgRedux<AppState>,
               private route: ActivatedRoute,
               private _duplicateService: DuplicateService,
-              private modalService: SdcUiServices.ModalService,
+              private modalService: ModalService,
               private _drawingBoardTreeService: DrawingBoardTreeService,
               private _networkPopupService: NetworkPopupService,
               private _vfModulePopuopService: VfModulePopupService,
@@ -120,7 +120,7 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit {
   @Output()
   highlightNode: EventEmitter<number> = new EventEmitter<number>();
 
-  @ViewChild('tree') tree: TreeComponent;
+  @ViewChild('tree', {static: false}) tree: TreeComponent;
   missingDataTooltip: string = Constants.Error.MISSING_VNF_DETAILS;
   currentNode: ITreeNode = null;
   flags: any;
@@ -228,7 +228,13 @@ export class DrawingBoardTreeComponent implements OnInit, AfterViewInit {
     this.highlightNode.emit(node.data.modelUniqueId);
     if (FeatureFlagsService.getFlagState(Features.FLAG_1906_COMPONENT_INFO, this.store)) {
       const serviceHierarchy = this._store.getState().service.serviceHierarchy[this.serviceModelId];
-      const model = node.data.getModel(node.data.modelName, node.data, serviceHierarchy);
+
+      const instanceModel = this._sharedTreeService.modelByIdentifiers(
+        serviceHierarchy, node.data.modelTypeName,
+        this._sharedTreeService.modelUniqueNameOrId(node.data), node.data.modelName
+      );
+
+      const model = node.data.getModel(instanceModel);
       const modelInfoItems = node.data.getInfo(model, node.data);
       const componentInfoModel: ComponentInfoModel = this._sharedTreeService.addGeneralInfoItems(modelInfoItems, node.data.componentInfoType, model, node.data);
       ComponentInfoService.triggerComponentInfoChange.next(componentInfoModel);
index ea23629..6109862 100644 (file)
           <div><span title="{{node.data.type}}"
                      [attr.data-tests-id]="'node-type-indicator'">{{node?.data?.typeName}}</span></div>
           <div *ngIf="isLinkedInstance(node?.data)">
-            <svg-icon
+            <custom-icon
               [ngClass]="'link'"
               class="icon-link"
               [size]="'small'"
               [name]="'link'">
-            </svg-icon>
+            </custom-icon>
           </div>
         </div>
         <div class="model-info" [ngClass]="{'rightBorder' : pageMode === 'VIEW'}">
                          [enabled]="isEnabled(currentNode, serviceModelId, contextMenuOption.methodName)">
               <div [attr.data-tests-id]="contextMenuOption.dataTestId">
                 <div style="float: left;margin-top: 3px;">
-                  <svg-icon
+                  <custom-icon
                     class="icon-edit"
                     [ngClass]="contextMenuOption.iconClass"
                     [size]="'small'"
                     [name]="contextMenuOption.iconClass">
-                </svg-icon></div>
+                </custom-icon></div>
                 <div style="padding-left: 25px;">{{getcontextMenuOptionLabel(contextMenuOption)}}</div>
               </div>
             </ng-template>
             tooltipPlacement="left"
             [attr.data-tests-id]="'node-'+ node.data.modelId + '-' + node.data.modelName +'-alert-icon'"
             class="icon-alert">
-              <svg-icon
+              <custom-icon
                 [mode]="'warning'"
                 [testId]="'icon-alert'"
                 [size]="'medium'"
                 [name]="'alert-triangle-o'">
-              </svg-icon>
+              </custom-icon>
           </span>
         </div>
 
index 6423e8a..2f8ece2 100644 (file)
@@ -2,12 +2,12 @@ import {DuplicateService} from './duplicate.service';
 import {LogService} from '../../../shared/utils/log/log.service';
 import {NgRedux} from '@angular-redux/store';
 import {ITreeNode} from "angular-tree-component/dist/defs/api";
-import {SdcUiServices} from "onap-ui-angular";
-import {IModalConfig} from 'onap-ui-angular/dist/components/common';
 import {AppState} from "../../../shared/store/reducers";
 import {getTestBed, TestBed} from "@angular/core/testing";
 import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 import {SharedTreeService} from "../objectsToTree/shared.tree.service";
+import {IModalConfig} from "../../../shared/components/customModal/models/modal.model";
+import {ModalService} from "../../../shared/components/customModal/services/modal.service";
 
 class MockAppStore<T> {
   getState(){
@@ -73,7 +73,7 @@ describe('Drawing board tree service', () => {
         LogService,
         {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
index c8338cb..c3a5a28 100644 (file)
@@ -8,19 +8,20 @@ import {VfModuleMap} from "../../../shared/models/vfModulesMap";
 import * as _ from "lodash";
 import {DefaultDataGeneratorService} from "../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
 import {TypeNodeInformation} from "../typeNodeInformation.model";
-import {SdcUiCommon, SdcUiServices} from "onap-ui-angular";
+import {SdcUiCommon} from "onap-ui-angular";
 import {changeInstanceCounter, duplicateBulkInstances} from "../../../shared/storeUtil/utils/general/general.actions";
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
 import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
 import {Utils} from "../../../shared/utils/utils";
 import {SharedTreeService} from "../objectsToTree/shared.tree.service";
+import {ModalService} from "../../../shared/components/customModal/services/modal.service";
 
 @Injectable()
 export class DuplicateService {
 
   constructor(private _logService: LogService,
               private sharedTreeService : SharedTreeService,
-              private _store: NgRedux<AppState>, modalService: SdcUiServices.ModalService) {
+              private _store: NgRedux<AppState>, modalService: ModalService) {
     this.modalService = modalService;
   }
 
@@ -35,7 +36,7 @@ export class DuplicateService {
   maxNumberOfDuplicate: number = 0;
   storeKey: string = null;
   padding = '0000';
-  modalService: SdcUiServices.ModalService;
+  modalService: ModalService;
   store: NgRedux<AppState>;
   existingNames: { [key: string]: any };
   currentNode: ITreeNode = null;
index 5ae6437..eae534c 100644 (file)
@@ -1,6 +1,6 @@
 import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {AvailableNodeIcons} from "../../available-models-tree/available-models-tree.service";
-import {ComponentInfoModel, ComponentInfoType} from "../../component-info/component-info-model";
+import {ComponentInfoType} from "../../component-info/component-info-model";
 import {ModelInformationItem} from "../../../../shared/components/model-information/model-information.component";
 
 export interface ILevelNodeInfo {
@@ -44,12 +44,11 @@ export interface ILevelNodeInfo {
   updatePosition(node, that, instanceId, parentStoreKey?) : void;
 
   /***********************************************************
-   * return object instance
-   * @param modelId - The model id
-   * @param serviceHierarchy - The serviceHierarchy store
-   * @param instance - existing instance details
+   * return a NodeModel object instance
+   * @param instanceModel - The model of the instance (usually extracted from
+   *        serviceHierarchy store)
    ************************************************************/
-  getModel(modelId: string, instance: any, serviceHierarchy): any;
+  getModel(instanceModel: any): any;
 
   /***********************************************************
    * return dynamic inputs of current model
@@ -63,8 +62,9 @@ export interface ILevelNodeInfo {
    * @param model - The model of current object
    * @param parentModel
    * @param storeKey - instance storeKey if exist (for duplicate)
+   * @param serviceModelId
    ************************************************************/
-  createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string): any
+  createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any
 
   /***********************************************************
    * return if instance has some missing data
index f8ce819..2f143fa 100644 (file)
@@ -24,7 +24,7 @@ describe('Collection Resource Model Info', () => {
   let collectionResourceModel: CollectionResourceModelInfo;
   let  _sharedTreeService : SharedTreeService;
 
-  beforeEach(() => {
+  beforeEach(done => (async () => {
     TestBed.configureTestingModule({
       imports: [HttpClientTestingModule, NgReduxTestingModule],
       providers: [
@@ -38,16 +38,17 @@ describe('Collection Resource Model Info', () => {
         FeatureFlagsService,
         ComponentInfoService,
         IframeService]
-    }).compileComponents();
-
+    });
+    await TestBed.compileComponents();
     injector = getTestBed();
     _store = injector.get(NgRedux);
     _componentInfoService = injector.get(ComponentInfoService);
+    _sharedTreeService = injector.get(SharedTreeService);
 
     collectionResourceModel = new CollectionResourceModelInfo(_store, _sharedTreeService);
 
 
-  });
+  })().then(done).catch(done.fail));
 
   test('collection resource should be defined', () => {
     expect(collectionResourceModel).toBeDefined();
@@ -82,10 +83,7 @@ describe('Collection Resource Model Info', () => {
   });
 
   test('getModel should return collectionResource model', () => {
-    let model: CollectionResourceModel = collectionResourceModel.getModel('CR_sanity 0', <any>{
-      originalName : 'CR_sanity 0'
-    }, getServiceHierarchy());
-    expect(model.type).toEqual('CR');
+    expect(collectionResourceModel.getModel({})).toBeInstanceOf(CollectionResourceModel);
   });
 
   test('cr getMenuAction: delete', ()=>{
@@ -100,1108 +98,4 @@ describe('Collection Resource Model Info', () => {
     expect(result['delete']['method']).toHaveBeenCalledWith(node, serviceModelId);
   });
 
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "collectionResources": {
-        "CR_sanity 0": {
-          "uuid": "3467f91f-1a2a-4013-a5ed-8ad99d4e06ad",
-          "invariantUuid": "d0060da6-82b8-4ca0-9758-5eb2b111b926",
-          "description": "CR_sanity",
-          "name": "CR_sanity",
-          "version": "1.0",
-          "customizationUuid": "7160c618-9314-4c09-8717-b77f3d29d946",
-          "inputs": {},
-          "commands": {},
-          "properties": {
-            "cr_sanity..Fixed..0_quantity": "10",
-            "cr_sanity..NetworkCollection..0_network_collection_function": "ABCD",
-            "ecomp_generated_naming": "false",
-            "cr_sanity..NetworkCollection..0_network_collection_description": "ABCD"
-          },
-          "type": "CR",
-          "category": "Network L2-3",
-          "subcategory": "Infrastructure",
-          "resourceVendor": "ATT",
-          "resourceVendorRelease": "2018.06",
-          "resourceVendorModelNumber": "",
-          "customizationUUID": "7160c618-9314-4c09-8717-b77f3d29d946",
-          "networksCollection": {
-            "cr_sanity..NetworkCollection..0": {
-              "uuid": "445d7fa8-3e59-4606-bd76-30ba5fc677d3",
-              "invariantUuid": "9dc623b8-0ae8-47ad-a791-a21b8d8e94a8",
-              "name": "cr_sanity..NetworkCollection..0",
-              "version": "1",
-              "networkCollectionProperties": {
-                "networkCollectionFunction": "ABCD",
-                "networkCollectionDescription": "ABCD"
-              }
-            }
-          }
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
-
 });
index 564e04b..d144837 100644 (file)
@@ -28,17 +28,15 @@ export class CollectionResourceModelInfo implements ILevelNodeInfo{
 
   updateDynamicInputsDataFromModel = (currentModel): any => [];
 
-  getModel = (collectionResourceModelId: string, instance: CollectionResourceInstance, serviceHierarchy): CollectionResourceModel => {
-    const originalModelName = instance.originalName ? instance.originalName : collectionResourceModelId;
-    return new CollectionResourceModel(serviceHierarchy[this.name][originalModelName]);
+  getModel = (instanceModel): CollectionResourceModel => {
+    return new CollectionResourceModel(instanceModel);
   };
 
-
-  createInstanceTreeNode = (instance: CollectionResourceInstance, model: CollectionResourceModel, parentModel, storeKey: string): CollectionResourceTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
       let node = new CollectionResourceTreeNode(instance, model, storeKey);
       node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
       node.typeName = this.typeName;
-      node.menuActions = this.getMenuAction(<any>node, model.uuid);
+      node.menuActions = this.getMenuAction(<any>node, serviceModelId);
       node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
       node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
       return node;
index 6b67de6..aa69b53 100644 (file)
@@ -1,11 +1,12 @@
 import {HttpClientTestingModule} from "@angular/common/http/testing";
-import {TestBed} from "@angular/core/testing";
+import {getTestBed, TestBed} from "@angular/core/testing";
 import {MockNgRedux, NgReduxTestingModule} from "@angular-redux/store/testing";
 import {DynamicInputsService} from "../../dynamicInputs.service";
 import {ConfigurationModelInfo} from "./configuration.model.info";
 import {SharedTreeService} from "../../shared.tree.service";
 
 describe('Vnf Model Info', () => {
+  let injector;
   let  _dynamicInputsService : DynamicInputsService;
   let  _sharedTreeService : SharedTreeService;
 
@@ -18,6 +19,9 @@ describe('Vnf Model Info', () => {
         DynamicInputsService]
     });
     await TestBed.compileComponents();
+
+    injector = getTestBed();
+    _sharedTreeService = injector.get(SharedTreeService);
   })().then(done).catch(done.fail));
 
   test('ConfigurationModelInfo should be defined', () => {
@@ -50,1451 +54,8 @@ describe('Vnf Model Info', () => {
 
   test('getModel should return Configuration model', () => {
     let configurationModelInfo: ConfigurationModelInfo = new ConfigurationModelInfo(_dynamicInputsService, _sharedTreeService);
-    let model = configurationModelInfo.getModel('2017-388_PASQUALE-vPE 1__configuration', getServiceHierarchy());
-    expect(model.uuid).toEqual('0903e1c0-8e03-4936-b5c2-260653b96413');
+    let model = configurationModelInfo.getModel({ uuid: 'foo' });
+    expect(model.uuid).toEqual('foo');
   });
 
-
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        }
-      },
-      "collectionResources": {},
-      "configurations": {
-        "2017-388_PASQUALE-vPE 1__configuration": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        }
-
-      },
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
 });
index 0d1a9aa..9845fb6 100644 (file)
@@ -26,20 +26,16 @@ export class ConfigurationModelInfo implements ILevelNodeInfo{
   getType = () : string => "Configuration";
 
   /***********************************************************
-   * return configuration model
-   * @param configurationModelId - current Model id
-   * @param serviceHierarchy - serviceHierarchy
+   * @param instanceModel - The model of the instance (usually extracted from serviceHierarchy store)
    ************************************************************/
-  getModel = (configurationModelId : string, serviceHierarchy) : any =>{
-    if(!_.isNil(serviceHierarchy)){
-      if(!_.isNil(serviceHierarchy[this.name]) && !_.isNil(serviceHierarchy[this.name][configurationModelId])){
-        return serviceHierarchy[this.name][configurationModelId];
-      }
+  getModel = (instanceModel: any) : any =>{
+    if (!_.isNil(instanceModel)) {
+      return instanceModel;
     }
     return {};
   };
 
-  createInstanceTreeNode(instance: any, model: any, storeKey: string): any {return null;}
+  createInstanceTreeNode(instance: any, model: any, storeKey: string, serviceModelId: string): any {return null;}
 
   childNames: string[];
 
index 6c83828..9511458 100644 (file)
@@ -69,7 +69,7 @@ describe('NCF Model Info', () => {
       typeName: "NCF"
     };
 
-    const ncfTreeNode: NcfTreeNode = ncfModel.createInstanceTreeNode(instance, {}, parentModel, "6b3536cf-3a12-457f-abb5-fa2203e0d923");
+    const ncfTreeNode: NcfTreeNode = ncfModel.createInstanceTreeNode(instance, {}, parentModel, "6b3536cf-3a12-457f-abb5-fa2203e0d923", "dd182d7d-6949-4b90-b3cc-5befe400742e");
     expect(ncfTreeNode).toMatchObject(expected);
   });
 
index 4db41c0..650d975 100644 (file)
@@ -32,12 +32,12 @@ export class NcfModelInfo implements ILevelNodeInfo {
 
   updateDynamicInputsDataFromModel = (currentModel): any => [];
 
-  getModel = (modelId: string, instance: any, serviceHierarchy): any => {
+  getModel = (instanceModel: any): any => {
     return new Level1Model();
   };
 
 
-  createInstanceTreeNode = (instance: Level1Instance, model: Level1Model, parentModel, storeKey: string): NcfTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let modelVersion: string = null;
     if (parentModel.networksCollection && instance.originalName) {
       const ncfRealModel: NcfModelInterface = parentModel.networksCollection[instance.originalName];
@@ -47,7 +47,7 @@ export class NcfModelInfo implements ILevelNodeInfo {
     }
 
     let node = new NcfTreeNode(instance, model, storeKey, modelVersion);
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.typeName = this.typeName;
     return node;
   };
index f26ab0c..bb8e882 100644 (file)
@@ -13,6 +13,7 @@ import {IframeService} from "../../../../../shared/utils/iframe.service";
 import {DuplicateService} from "../../../duplicate/duplicate.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
+import {NetworkModel} from "../../../../../shared/models/networkModel";
 
 class MockAppStore<T> {
   getState() {
@@ -146,8 +147,7 @@ describe('Network Model Info', () => {
   });
 
   test('getModel should return Network model', () => {
-    let model = networkModel.getModel('2017-388_PASQUALE-vPE 1_1', <any>{}, getServiceHierarchy());
-    expect(model.type).toEqual('VL');
+    expect(networkModel.getModel({})).toBeInstanceOf(NetworkModel);
   });
 
   test('showNodeIcons should return false if reachLimit of max', () => {
@@ -387,1259 +387,4 @@ describe('Network Model Info', () => {
     };
   }
 
-
-  function getServiceHierarchy() {
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {
-        "2017-388_PASQUALE-vPE 1_1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VL",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        }
-      },
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
 });
index 486ac93..ce1af45 100644 (file)
@@ -1,13 +1,15 @@
 import {DynamicInputsService} from "../../dynamicInputs.service";
 import {ILevelNodeInfo} from "../basic.model.info";
-import {NetworkInstance} from "../../../../../shared/models/networkInstance";
 import {NetworkModel} from "../../../../../shared/models/networkModel";
 import {NetworkTreeNode} from "../../../../../shared/models/networkTreeNode";
 import {SharedTreeService} from "../../shared.tree.service";
 import {InputType} from "../../../../../shared/models/inputTypes";
 import {NgRedux} from "@angular-redux/store";
 import {AppState} from "../../../../../shared/store/reducers";
-import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
+import {
+  GenericFormPopupComponent,
+  PopupType
+} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
 import {DialogService} from "ng2-bootstrap-modal";
 import {NetworkPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/network/network.popup.service";
 import * as _ from "lodash";
@@ -16,14 +18,18 @@ import {AvailableNodeIcons} from "../../../available-models-tree/available-model
 import {DuplicateVnfComponent} from "../../../duplicate/duplicate-vnf.component";
 import {changeInstanceCounter, removeInstance} from "../../../../../shared/storeUtil/utils/general/general.actions";
 import {IframeService} from "../../../../../shared/utils/iframe.service";
-import {SdcUiServices} from "onap-ui-angular";
 import {DuplicateService} from "../../../duplicate/duplicate.service";
 import {ServiceInstanceActions} from "../../../../../shared/models/serviceInstanceActions";
-import {deleteActionNetworkInstance, undoDeleteActionNetworkInstance, updateNetworkPosition} from "../../../../../shared/storeUtil/utils/network/network.actions";
+import {
+  deleteActionNetworkInstance,
+  undoDeleteActionNetworkInstance,
+  updateNetworkPosition
+} from "../../../../../shared/storeUtil/utils/network/network.actions";
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
 import {ComponentInfoType} from "../../../component-info/component-info-model";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
+import {ModalService} from "../../../../../shared/components/customModal/services/modal.service";
 
 export class NetworkModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -31,7 +37,7 @@ export class NetworkModelInfo implements ILevelNodeInfo {
               private _dialogService: DialogService,
               private _networkPopupService: NetworkPopupService,
               private _duplicateService: DuplicateService,
-              private modalService: SdcUiServices.ModalService,
+              private modalService: ModalService,
               private _iframeService: IframeService,
               private _featureFlagsService: FeatureFlagsService,
               private _store: NgRedux<AppState>) {
@@ -58,14 +64,13 @@ export class NetworkModelInfo implements ILevelNodeInfo {
   };
 
   /***********************************************************
-   * return network model
-   * @param networkModelId - current Model id
-   * @param instance
-   * @param serviceHierarchy - serviceHierarchy
+   * return a NodeModel object instance
+   * @param instanceModel - The model of the instance (usually extracted from serviceHierarchy store)
    ************************************************************/
-  getModel = (networkModelId: string, instance: NetworkInstance, serviceHierarchy): NetworkModel => {
-    const originalModelName = instance.originalName ? instance.originalName : networkModelId;
-    return new NetworkModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
+  getModel = (instanceModel: any): NetworkModel => {
+    return new NetworkModel(
+      instanceModel,
+      this._featureFlagsService.getAllFlags());
   };
 
 
@@ -76,11 +81,11 @@ export class NetworkModelInfo implements ILevelNodeInfo {
    * @param parentModel
    * @param storeKey - store key if exist
    ************************************************************/
-  createInstanceTreeNode = (instance: NetworkInstance, model: NetworkModel, parentModel, storeKey: string): NetworkTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let node = new NetworkTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node = this._sharedTreeService.addingStatusProperty(node);
@@ -225,8 +230,8 @@ export class NetworkModelInfo implements ILevelNodeInfo {
             });
           }
         },
-        visible: (node) => node.data.parentType !== 'VRF' && this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => node.data.parentType !== 'VRF' && this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => node.data.parentType !== 'VRF' && this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => node.data.parentType !== 'VRF' && this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete: {
         method: (node, serviceModelId) => {
index ca041e0..8675d36 100644 (file)
@@ -14,14 +14,17 @@ import {MockNgRedux, NgReduxTestingModule} from "@angular-redux/store/testing";
 import {HttpClient, HttpHandler} from "@angular/common/http";
 import {CollectionResourceModel} from "../../../../../shared/models/collectionResourceModel";
 import {ComponentInfoType} from "../../../component-info/component-info-model";
+import {VNFModel} from "../../../../../shared/models/vnfModel";
+import {PNFModel} from "../../../../../shared/models/pnfModel";
 
 
 describe('PNF model info', () => {
   let injector;
   let _componentInfoService: ComponentInfoService;
   let _store: NgRedux<AppState>;
-  let pnfModel: PnfModelInfo =  new PnfModelInfo();
-  beforeEach(() => {
+  let _sharedTreeService;
+  let pnfModel: PnfModelInfo;
+  beforeEach(done => (async () => {
     TestBed.configureTestingModule({
       imports: [HttpClientTestingModule, NgReduxTestingModule],
       providers: [
@@ -35,12 +38,14 @@ describe('PNF model info', () => {
         FeatureFlagsService,
         ComponentInfoService,
         IframeService]
-    }).compileComponents();
-
+    });
+    await TestBed.compileComponents();
     injector = getTestBed();
     _store = injector.get(NgRedux);
+    _sharedTreeService = injector.get(SharedTreeService);
+    pnfModel = new PnfModelInfo(_sharedTreeService);
     _componentInfoService = injector.get(ComponentInfoService);
-  });
+  })().then(done).catch(done.fail));
 
   test('pnf model should be defined', () => {
     expect(pnfModel).toBeDefined();
@@ -74,61 +79,7 @@ describe('PNF model info', () => {
   });
 
   test('getModel should return pnf model', () => {
-    let model: CollectionResourceModel = pnfModel.getModel('PNF1', <any>{
-      originalName : 'PNF1'
-    }, getServiceHierarchy());
-    expect(model.type).toEqual('PNF');
+    expect(pnfModel.getModel({})).toBeInstanceOf(PNFModel);
   });
 
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "12550cd7-7708-4f53-a09e-41d3d6327ebc",
-        "invariantUuid": "561faa57-7bbb-40ec-a81c-c0d4133e98d4",
-        "name": "AIM Transport SVC_ym161f",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "Network L1-3",
-        "serviceType": "TRANSPORT",
-        "serviceRole": "AIM",
-        "description": "AIM Transport service",
-        "serviceEcompNaming": "true",
-        "instantiationType": "Macro",
-        "inputs": {},
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other",
-          "viewEditUI": "legacy"
-        }
-      },
-      "vnfs": {},
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {},
-      "volumeGroups": {},
-      "pnfs": {
-        "PNF1": {
-          "uuid": "1c831fa9-28a6-4778-8c1d-80b9e769f2ed",
-          "invariantUuid": "74e13a12-dac9-4fba-b102-cd242d9e7f02",
-          "description": "AIM Transport service",
-          "name": "AIM PNF Model",
-          "version": "1.0",
-          "customizationUuid": "dce78da7-c842-47a1-aba2-2de1cd03ab7a",
-          "inputs": {},
-          "commands": {},
-          "properties": {
-            "nf_function": "SDNGW",
-            "nf_role": "pD2IPE",
-            "ecomp_generated_naming": "false",
-            "nf_type": "ROUTER"
-          },
-          "type": "PNF"
-        }
-      },
-      "vnfGroups": {}
-    }
-  }
 })
index dc01b87..a7931b2 100644 (file)
@@ -5,12 +5,15 @@ import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
 import {PnfInstance} from "app/shared/models/pnfInstance";
 import {PNFModel} from "../../../../../shared/models/pnfModel";
-import {PnfTreeNode} from "../../../../../shared/models/pnfTreeNode";
+import {SharedTreeService} from "../../shared.tree.service";
+import {NodeModelResponseInterface} from "../../../../../shared/models/nodeModel";
 
 
 export class PnfModelInfo implements ILevelNodeInfo{
 
-  constructor(){}
+  constructor(
+    private _sharedTreeService: SharedTreeService,
+  ){}
 
   name: string = 'pnfs';
   type: string ='PNF';
@@ -18,7 +21,7 @@ export class PnfModelInfo implements ILevelNodeInfo{
   childNames: string[];
   componentInfoType = ComponentInfoType.PNF;
 
-  createInstanceTreeNode = (instance: PnfInstance, model: PNFModel, parentModel: any, storeKey: string): PnfTreeNode => null;
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => null;
 
   getInfo(model, instance): ModelInformationItem[] {
     return [];
@@ -28,9 +31,8 @@ export class PnfModelInfo implements ILevelNodeInfo{
     return {};
   }
 
-  getModel = (pnfModelId: string, instance: PnfInstance, serviceHierarchy): PNFModel => {
-    const originalModelName = instance.originalName ? instance.originalName : pnfModelId;
-    return new PNFModel(serviceHierarchy[this.name][originalModelName]);
+  getModel = (instanceModel: any): PNFModel => {
+    return new PNFModel(instanceModel);
   };
 
   getNextLevelObject(): any { return null;  }
index 59ef35a..8073d17 100644 (file)
@@ -109,10 +109,7 @@ describe('Related Vnf member Model Info', () => {
   });
 
   test('getModel should return VNF model', () => {
-    let model: VNFModel = relatedVnfMemeber.getModel('2017-388_PASQUALE-vPE 1', <any>{
-      originalName : '2017-388_PASQUALE-vPE 1'
-    }, getServiceHierarchy());
-    expect(model.type).toEqual('VF');
+    expect(relatedVnfMemeber.getModel({})).toBeInstanceOf(VNFModel);
   });
 
 
@@ -141,1073 +138,4 @@ describe('Related Vnf member Model Info', () => {
     expect(result['undoDelete']['method']).toHaveBeenCalledWith(node, serviceModelId);
   });
 
-
-
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
 });
index c8807e8..fdd4c22 100644 (file)
@@ -11,7 +11,6 @@ import {
   removeRelatedVnfMemberInstance,
   undoDeleteActionRelatedVnfMemberInstance
 } from "../../../../../shared/storeUtil/utils/relatedVnfMember/relatedVnfMember.actions";
-import {VnfInstance} from "../../../../../shared/models/vnfInstance";
 import {VNFModel} from "../../../../../shared/models/vnfModel";
 import {VnfTreeNode} from "../../../../../shared/models/vnfTreeNode";
 import {InputType} from "../../../../../shared/models/inputTypes";
@@ -48,14 +47,12 @@ export class RelatedVnfMemberInfoModel implements ILevelNodeInfo {
   };
 
   /***********************************************************
-   * return vnf model
-   * @param vnfModelId - current Model id
-   * @param instance - vnf instance
-   * @param serviceHierarchy - serviceHierarchy
+   * return a NodeModel object instance
+   * @param instanceModel - The model of the instance (usually extracted from
+   *        serviceHierarchy store)
    ************************************************************/
-  getModel = (vnfModelId: string, instance: VnfInstance, serviceHierarchy): VNFModel => {
-    const originalModelName = instance.originalName ? instance.originalName : vnfModelId;
-    return new VNFModel(serviceHierarchy[this.name][originalModelName]);
+  getModel = (instanceModel: any): VNFModel => {
+    return new VNFModel(instanceModel);
   };
 
 
@@ -65,12 +62,13 @@ export class RelatedVnfMemberInfoModel implements ILevelNodeInfo {
    * @param model - vnf model
    * @param parentModel
    * @param storeKey - store key if exist
+   * @param serviceModelId
    ************************************************************/
-  createInstanceTreeNode = (instance: VnfInstance, model: VNFModel, parentModel, storeKey: string): VnfTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let node = new VnfTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage: "";
     node = this._sharedTreeService.addingStatusProperty(node);
@@ -128,8 +126,8 @@ export class RelatedVnfMemberInfoModel implements ILevelNodeInfo {
         method : (node, serviceModelId) => {
           this._store.dispatch(deleteActionRelatedVnfMemberInstance(node.parent.data.vnfGroupStoreKey, node.data.vnfStoreKey, serviceModelId));
         },
-        visible: (node) => this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete : {
         method : (node, serviceModelId) => {
@@ -137,7 +135,7 @@ export class RelatedVnfMemberInfoModel implements ILevelNodeInfo {
 
         },
         visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
-        enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
+        enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent, serviceModelId) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
       }
     }
   }
index 2162318..c225687 100644 (file)
@@ -128,7 +128,29 @@ describe('VFModule Model Info', () => {
   });
 
   test('getModel should return Module model', () => {
-    let model = vfModuleModel.getModel('2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1',null, getServiceHierarchy());
+    let model = vfModuleModel.getModel({
+      "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
+      "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
+      "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
+      "description": null,
+      "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
+      "version": "6",
+      "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
+      "properties": {
+        "minCountInstances": 2,
+        "maxCountInstances": 3,
+        "initialCount": 0,
+        "vfModuleLabel": "PASQUALE_vRE_BV",
+        "baseModule": false
+      },
+      "inputs": {
+        "vnf_config_template_version": {
+          "type": "string"
+        }
+      },
+      "volumeGroupAllowed": true
+    });
+    expect(model).toBeInstanceOf(VfModule);
     expect(model.uuid).toEqual('25284168-24bb-4698-8cb4-3f509146eca5');
     expect(model.min).toBe(2);
     expect(model.max).toBe(3);
@@ -629,938 +651,4 @@ describe('VFModule Model Info', () => {
     };
   }
 
-
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1":{
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 2,
-                "maxCountInstances": 3,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 2,
-            "maxCountInstances": 3,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
 });
index 36b5ed0..f442e15 100644 (file)
@@ -74,20 +74,17 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
 
   /***********************************************************
    * return vfModule model
-   * @param vfModuleModelId - current Model id
-   * @param instance
-   * @param serviceHierarchy - serviceHierarchy
+   * @param instanceModel - The model of the instance (usually extracted from
+   *        serviceHierarchy store)
    ************************************************************/
-  getModel = (vfModuleModelId: string, instance, serviceHierarchy): Partial<VfModule> => {
-    if (!_.isNil(serviceHierarchy)) {
-      if (!_.isNil(serviceHierarchy[this.name]) && !_.isNil(serviceHierarchy[this.name][vfModuleModelId])) {
-        return new VfModule(serviceHierarchy[this.name][vfModuleModelId], this._featureFlagsService.getAllFlags());
-      }
+  getModel = (instanceModel: any): Partial<VfModule> => {
+    if (!_.isNil(instanceModel)) {
+      return new VfModule(instanceModel, this._featureFlagsService.getAllFlags());
     }
     return {};
   };
 
-  createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number): VfModuleTreeNode {
+  createNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string, index: number, serviceModelId: string): VfModuleTreeNode {
     let dynamicModelName = Object.keys(instance)[index];
     instance = instance[Object.keys(instance)[index]];
     const isEcompGeneratedNaming: boolean = this.isEcompGeneratedNaming(currentModel, parentModel);
@@ -97,7 +94,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
 
     newVfModule.missingData = this._sharedTreeService.hasMissingData(instance, newVfModule.dynamicInputs, isEcompGeneratedNaming, []);
     newVfModule.typeName = this.typeName;
-    newVfModule.menuActions = this.getMenuAction(<any>newVfModule, currentModel.uuid);
+    newVfModule.menuActions = this.getMenuAction(<any>newVfModule, serviceModelId);
     newVfModule.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     newVfModule.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
 
@@ -105,16 +102,16 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
     return newVfModule;
   }
 
-  createInstanceTreeNode(instance: VfModuleInstance, currentModel: VfModule, parentModel: VNFModel, modelName: string): VfModuleTreeNode | VfModuleTreeNode[] {
+  createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any {
     let numberOfChilds = Object.keys(instance).length;
     if (numberOfChilds > 1) {
       let result: VfModuleTreeNode[] = [];
       for (let i = 0; i < numberOfChilds; i++) {
-        result.push(this.createNode(instance, currentModel, parentModel, modelName, i));
+        result.push(this.createNode(instance, model, parentModel, storeKey, i, serviceModelId));
       }
       return result;
     } else {
-      return this.createNode(instance, currentModel, parentModel, modelName, 0);
+      return this.createNode(instance, model, parentModel, storeKey, 0, serviceModelId);
     }
   }
 
@@ -356,8 +353,8 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
         method: (node, serviceModelId) => {
           this._store.dispatch(deleteActionVfModuleInstance(node.data.dynamicModelName, node.parent.data.vnfStoreKey, serviceModelId))
         },
-        visible: (node) => this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete: {
         method: (node, serviceModelId) => {
@@ -365,7 +362,7 @@ export class VFModuleModelInfo implements ILevelNodeInfo {
           this._store.dispatch(deleteVFModuleField(node.data.modelName,  node.parent.data.vnfStoreKey, node.data.servicedId ,node.data.dynamicModelName, 'retainAssignments'));
         },
         visible: (node) => this._sharedTreeService.shouldShowUndoDelete(node),
-        enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
+        enable: (node, serviceModelId) => this._sharedTreeService.shouldShowUndoDelete(node) && this._sharedTreeService.shouldShowDelete(node.parent, serviceModelId) && !this._sharedTreeService.isServiceOnDeleteMode(serviceModelId)
       },
       upgrade: {
         method: (node, serviceModelId) => {
index f700ed4..53aeddd 100644 (file)
@@ -145,10 +145,7 @@ describe('Vnf Model Info', () => {
   });
 
   test('getModel should return VNF model', () => {
-    let model: VNFModel = vnfModel.getModel('2017-388_PASQUALE-vPE 1', <any>{
-      originalName : '2017-388_PASQUALE-vPE 1'
-    }, getServiceHierarchy());
-    expect(model.type).toEqual('VF');
+    expect(vnfModel.getModel({})).toBeInstanceOf(VNFModel);
   });
 
   test('showNodeIcons should return false if reachLimit of max', ()=>{
@@ -607,1072 +604,4 @@ describe('Vnf Model Info', () => {
     };
   }
 
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfs": {
-        "2017-388_PASQUALE-vPE 1": {
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "1.0",
-          "customizationUuid": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-388_PASQUALE-vPE 0": {
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-388_PASQUALE-vPE",
-          "version": "4.0",
-          "customizationUuid": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "vfModules": {},
-          "volumeGroups": {},
-          "vfcInstanceGroups": {}
-        },
-        "2017-488_PASQUALE-vPE 0": {
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "invariantUuid": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "description": "Name PASQUALE vPE Description The provider edge function for the PASQUALE service supported by the Junipers VMX product Category Router Vendor Juniper Vendor Release Code 17.2 Owners Mary Fragale. Updated 9-25 to use v8.0 of the Juniper Valid 2 VLM",
-          "name": "2017-488_PASQUALE-vPE",
-          "version": "5.0",
-          "customizationUuid": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "ASN": {
-              "type": "string",
-              "description": "AV/PE",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "AV_vPE"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": null,
-              "constraints": [],
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "commands": {
-            "vnf_config_template_version": {
-              "displayName": "vnf_config_template_version",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_config_template_version"
-            },
-            "bandwidth_units": {
-              "displayName": "bandwidth_units",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth_units"
-            },
-            "bandwidth": {
-              "displayName": "bandwidth",
-              "command": "get_input",
-              "inputName": "pasqualevpe0_bandwidth"
-            },
-            "AIC_CLLI": {
-              "displayName": "AIC_CLLI",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_AIC_CLLI"
-            },
-            "ASN": {
-              "displayName": "ASN",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_ASN"
-            },
-            "vnf_instance_name": {
-              "displayName": "vnf_instance_name",
-              "command": "get_input",
-              "inputName": "2017488_pasqualevpe0_vnf_instance_name"
-            }
-          },
-          "properties": {
-            "vmxvre_retype": "RE-VMX",
-            "vnf_config_template_version": "get_input:2017488_pasqualevpe0_vnf_config_template_version",
-            "sriov44_net_id": "48d399b3-11ee-48a8-94d2-f0ea94d6be8d",
-            "int_ctl_net_id": "2f323477-6936-4d01-ac53-d849430281d9",
-            "vmxvpfe_sriov41_0_port_mac": "00:11:22:EF:AC:DF",
-            "int_ctl_net_name": "VMX-INTXI",
-            "vmx_int_ctl_prefix": "10.0.0.10",
-            "sriov43_net_id": "da349ca1-6de9-4548-be88-2d88e99bfef5",
-            "sriov42_net_id": "760669ba-013d-4d9b-b0e7-4151fe2e6279",
-            "sriov41_net_id": "25ad52d5-c165-40f8-b3b0-ddfc2373280a",
-            "nf_type": "vPE",
-            "vmxvpfe_int_ctl_ip_1": "10.0.0.10",
-            "is_AVPN_service": "false",
-            "vmx_RSG_name": "vREXI-affinity",
-            "vmx_int_ctl_forwarding": "l2",
-            "vmxvre_oam_ip_0": "10.0.0.10",
-            "vmxvpfe_sriov44_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_sriov41_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov42_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov44_0_port_unknownunicastallow": "true",
-            "vmxvre_image_name_0": "VRE-ENGINE_17.2-S2.1.qcow2",
-            "vmxvre_instance": "0",
-            "vmxvpfe_sriov43_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvre_flavor_name": "ns.c1r16d32.v5",
-            "vmxvpfe_volume_size_0": "40.0",
-            "vmxvpfe_sriov43_0_port_vlanfilter": "4001",
-            "nf_naming": "{ecomp_generated_naming=false}",
-            "nf_naming_code": "Navneet",
-            "vmxvre_name_0": "vREXI",
-            "vmxvpfe_sriov42_0_port_vlanstrip": "false",
-            "vmxvpfe_volume_name_0": "vPFEXI_FBVolume",
-            "max_instances": "3",
-            "vmx_RSG_id": "bd89a33c-13c3-4a04-8fde-1a57eb123141",
-            "vmxvpfe_image_name_0": "VPE_ROUTING-ENGINE_17.2R1-S2.1.qcow2",
-            "vmxvpfe_sriov43_0_port_unknownunicastallow": "true",
-            "vmxvpfe_sriov44_0_port_unknownmulticastallow": "true",
-            "vmxvre_console": "vidconsole",
-            "vmxvpfe_sriov44_0_port_vlanfilter": "4001",
-            "vmxvpfe_sriov42_0_port_mac": "00:11:22:EF:AC:DF",
-            "vmxvpfe_volume_id_0": "47cede15-da2f-4397-a101-aa683220aff3",
-            "vmxvpfe_sriov42_0_port_unknownmulticastallow": "true",
-            "min_instances": "1",
-            "vmxvpfe_sriov44_0_port_vlanstrip": "false",
-            "vf_module_id": "123",
-            "nf_function": "JAI",
-            "vmxvpfe_sriov43_0_port_unknownmulticastallow": "true",
-            "vmxvre_int_ctl_ip_0": "10.0.0.10",
-            "ecomp_generated_naming": "false",
-            "AIC_CLLI": "get_input:2017488_pasqualevpe0_AIC_CLLI",
-            "vnf_name": "mtnj309me6vre",
-            "vmxvpfe_sriov41_0_port_unknownunicastallow": "true",
-            "vmxvre_volume_type_1": "HITACHI",
-            "vmxvpfe_sriov44_0_port_broadcastallow": "true",
-            "vmxvre_volume_type_0": "HITACHI",
-            "vmxvpfe_volume_type_0": "HITACHI",
-            "vmxvpfe_sriov43_0_port_broadcastallow": "true",
-            "bandwidth_units": "get_input:pasqualevpe0_bandwidth_units",
-            "vnf_id": "123",
-            "vmxvre_oam_prefix": "24",
-            "availability_zone_0": "mtpocfo-kvm-az01",
-            "ASN": "get_input:2017488_pasqualevpe0_ASN",
-            "vmxvre_chassis_i2cid": "161",
-            "vmxvpfe_name_0": "vPFEXI",
-            "bandwidth": "get_input:pasqualevpe0_bandwidth",
-            "availability_zone_max_count": "1",
-            "vmxvre_volume_size_0": "45.0",
-            "vmxvre_volume_size_1": "50.0",
-            "vmxvpfe_sriov42_0_port_broadcastallow": "true",
-            "vmxvre_oam_gateway": "10.0.0.10",
-            "vmxvre_volume_name_1": "vREXI_FAVolume",
-            "vmxvre_ore_present": "0",
-            "vmxvre_volume_name_0": "vREXI_FBVolume",
-            "vmxvre_type": "0",
-            "vnf_instance_name": "get_input:2017488_pasqualevpe0_vnf_instance_name",
-            "vmxvpfe_sriov41_0_port_unknownmulticastallow": "true",
-            "oam_net_id": "b95eeb1d-d55d-4827-abb4-8ebb94941429",
-            "vmx_int_ctl_len": "24",
-            "vmxvpfe_sriov43_0_port_vlanstrip": "false",
-            "vmxvpfe_sriov41_0_port_broadcastallow": "true",
-            "vmxvre_volume_id_1": "6e86797e-03cd-4fdc-ba72-2957119c746d",
-            "vmxvpfe_sriov41_0_port_vlanfilter": "4001",
-            "nf_role": "Testing",
-            "vmxvre_volume_id_0": "f4eacb79-f687-4e9d-b760-21847c8bb15a",
-            "vmxvpfe_sriov42_0_port_unknownunicastallow": "true",
-            "vmxvpfe_flavor_name": "ns.c20r16d25.v5"
-          },
-          "type": "VF",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "vfModules": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              },
-              "volumeGroupAllowed": true
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-              "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-              "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-              "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "version": "5",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-              "properties": {
-                "minCountInstances": 1,
-                "maxCountInstances": 1,
-                "initialCount": 1,
-                "vfModuleLabel": "PASQUALE_base_vPE_BV",
-                "baseModule": true
-              },
-              "inputs": {},
-              "volumeGroupAllowed": false
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {},
-              "volumeGroupAllowed": true
-            }
-          },
-          "volumeGroups": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-              "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-              "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-              "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "baseModule": false
-              },
-              "inputs": {
-                "vnf_config_template_version": {
-                  "type": "string",
-                  "description": "VPE Software Version",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_config_template_version"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-                  "constraints": null,
-                  "required": true,
-                  "default": "17.2"
-                },
-                "bandwidth_units": {
-                  "type": "string",
-                  "description": "Units of bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth_units"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth_units",
-                  "constraints": null,
-                  "required": true,
-                  "default": "Gbps"
-                },
-                "bandwidth": {
-                  "type": "string",
-                  "description": "Requested VPE bandwidth",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "bandwidth"
-                  },
-                  "fromInputName": "pasqualevpe0_bandwidth",
-                  "constraints": null,
-                  "required": true,
-                  "default": "10"
-                },
-                "AIC_CLLI": {
-                  "type": "string",
-                  "description": "AIC Site CLLI",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "AIC_CLLI"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-                  "constraints": null,
-                  "required": true,
-                  "default": "ATLMY8GA"
-                },
-                "vnf_instance_name": {
-                  "type": "string",
-                  "description": "The hostname assigned to the vpe.",
-                  "entry_schema": null,
-                  "inputProperties": {
-                    "sourceType": "HEAT",
-                    "vfModuleLabel": "PASQUALE_vRE_BV",
-                    "paramName": "vnf_instance_name"
-                  },
-                  "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-                  "constraints": null,
-                  "required": true,
-                  "default": "mtnj309me6"
-                }
-              }
-            },
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-              "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-              "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-              "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-              "description": null,
-              "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "version": "6",
-              "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-              "properties": {
-                "minCountInstances": 0,
-                "maxCountInstances": null,
-                "initialCount": 0,
-                "vfModuleLabel": "PASQUALE_vPFE_BV",
-                "baseModule": false
-              },
-              "inputs": {}
-            }
-          },
-          "vfcInstanceGroups": {}
-        }
-      },
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          },
-          "volumeGroupAllowed": true
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-          "uuid": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-          "invariantUuid": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-          "customizationUuid": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "version": "5",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-          "properties": {
-            "minCountInstances": 1,
-            "maxCountInstances": 1,
-            "initialCount": 1,
-            "vfModuleLabel": "PASQUALE_base_vPE_BV",
-            "baseModule": true
-          },
-          "inputs": {},
-          "volumeGroupAllowed": false
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {},
-          "volumeGroupAllowed": true
-        }
-      },
-      "volumeGroups": {
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1": {
-          "uuid": "25284168-24bb-4698-8cb4-3f509146eca5",
-          "invariantUuid": "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1",
-          "customizationUuid": "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vRE_BV",
-            "baseModule": false
-          },
-          "inputs": {
-            "vnf_config_template_version": {
-              "type": "string",
-              "description": "VPE Software Version",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_config_template_version"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_config_template_version",
-              "constraints": null,
-              "required": true,
-              "default": "17.2"
-            },
-            "bandwidth_units": {
-              "type": "string",
-              "description": "Units of bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth_units"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth_units",
-              "constraints": null,
-              "required": true,
-              "default": "Gbps"
-            },
-            "bandwidth": {
-              "type": "string",
-              "description": "Requested VPE bandwidth",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "bandwidth"
-              },
-              "fromInputName": "pasqualevpe0_bandwidth",
-              "constraints": null,
-              "required": true,
-              "default": "10"
-            },
-            "AIC_CLLI": {
-              "type": "string",
-              "description": "AIC Site CLLI",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "AIC_CLLI"
-              },
-              "fromInputName": "2017488_pasqualevpe0_AIC_CLLI",
-              "constraints": null,
-              "required": true,
-              "default": "ATLMY8GA"
-            },
-            "vnf_instance_name": {
-              "type": "string",
-              "description": "The hostname assigned to the vpe.",
-              "entry_schema": null,
-              "inputProperties": {
-                "sourceType": "HEAT",
-                "vfModuleLabel": "PASQUALE_vRE_BV",
-                "paramName": "vnf_instance_name"
-              },
-              "fromInputName": "2017488_pasqualevpe0_vnf_instance_name",
-              "constraints": null,
-              "required": true,
-              "default": "mtnj309me6"
-            }
-          }
-        },
-        "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2": {
-          "uuid": "0a0dd9d4-31d3-4c3a-ae89-a02f383e6a9a",
-          "invariantUuid": "eff8cc59-53a1-4101-aed7-8cf24ecf8339",
-          "customizationUuid": "3cd946bb-50e0-40d8-96d3-c9023520b557",
-          "description": null,
-          "name": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "version": "6",
-          "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
-          "properties": {
-            "minCountInstances": 0,
-            "maxCountInstances": null,
-            "initialCount": 0,
-            "vfModuleLabel": "PASQUALE_vPFE_BV",
-            "baseModule": false
-          },
-          "inputs": {}
-        }
-      },
-      "pnfs": {}
-    }
-  }
-
 });
index 355b5c5..d391f4a 100644 (file)
@@ -9,7 +9,10 @@ import {SharedTreeService} from "../../shared.tree.service";
 import {NgRedux} from "@angular-redux/store";
 import {AppState} from "../../../../../shared/store/reducers";
 import {DefaultDataGeneratorService} from "../../../../../shared/services/defaultDataServiceGenerator/default.data.generator.service";
-import {GenericFormPopupComponent, PopupType} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
+import {
+  GenericFormPopupComponent,
+  PopupType
+} from "../../../../../shared/components/genericFormPopup/generic-form-popup.component";
 import {DialogService} from 'ng2-bootstrap-modal';
 import {VnfPopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vnf/vnf.popup.service";
 import {VfModulePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModule/vfModule.popup.service";
@@ -17,13 +20,18 @@ import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
 import {DuplicateService} from "../../../duplicate/duplicate.service";
 import {DuplicateVnfComponent} from "../../../duplicate/duplicate-vnf.component";
-import {SdcUiServices} from "onap-ui-angular";
 import {IframeService} from "../../../../../shared/utils/iframe.service";
 import {changeInstanceCounter, removeInstance} from "../../../../../shared/storeUtil/utils/general/general.actions";
 import {MessageBoxData} from "../../../../../shared/components/messageBox/messageBox.data";
 import {MessageBoxService} from "../../../../../shared/components/messageBox/messageBox.service";
 import {ServiceInstanceActions} from "../../../../../shared/models/serviceInstanceActions";
-import {deleteActionVnfInstance, undoDeleteActionVnfInstance, undoUpgradeVnf, updateVnfPosition, upgradeVnf} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions";
+import {
+  deleteActionVnfInstance,
+  undoDeleteActionVnfInstance,
+  undoUpgradeVnf,
+  updateVnfPosition,
+  upgradeVnf
+} from "../../../../../shared/storeUtil/utils/vnf/vnf.actions";
 import * as _ from 'lodash';
 import {IModalConfig} from "onap-ui-angular/dist/modals/models/modal-config";
 import {ComponentInfoType} from "../../../component-info/component-info-model";
@@ -31,6 +39,7 @@ import {ComponentInfoService} from "../../../component-info/component-info.servi
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
 import {VfModuleUpgradePopupService} from "../../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
+import {ModalService} from "../../../../../shared/components/customModal/services/modal.service";
 
 export class VnfModelInfo implements ILevelNodeInfo {
   constructor(private _dynamicInputsService: DynamicInputsService,
@@ -41,7 +50,7 @@ export class VnfModelInfo implements ILevelNodeInfo {
               private _vfModulePopupService: VfModulePopupService,
               private _vfModuleUpgradePopupService: VfModuleUpgradePopupService,
               private _duplicateService: DuplicateService,
-              private modalService: SdcUiServices.ModalService,
+              private modalService: ModalService,
               private _iframeService: IframeService,
               private _componentInfoService: ComponentInfoService,
               private _featureFlagsService: FeatureFlagsService,
@@ -78,24 +87,25 @@ export class VnfModelInfo implements ILevelNodeInfo {
    * @param instance - vnf instance
    * @param serviceHierarchy - serviceHierarchy
    ************************************************************/
-  getModel = (vnfModelId: string, instance: VnfInstance, serviceHierarchy): VNFModel => {
-    const originalModelName = instance.originalName ? instance.originalName : vnfModelId;
-    return new VNFModel(serviceHierarchy[this.name][originalModelName], this._featureFlagsService.getAllFlags());
+  getModel = (instanceModel: any): VNFModel => {
+    return new VNFModel(
+      instanceModel,
+      this._featureFlagsService.getAllFlags());
   };
 
-
   /***********************************************************
    * return vnf instance tree node
    * @param instance - vnf instance
    * @param model - vnf model
    * @param parentModel
    * @param storeKey - store key if exist
+   * @param serviceModelId
    ************************************************************/
-  createInstanceTreeNode = (instance: VnfInstance, model: VNFModel, parentModel, storeKey: string): VnfTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let node = new VnfTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node = this._sharedTreeService.addingStatusProperty(node);
@@ -260,8 +270,8 @@ export class VnfModelInfo implements ILevelNodeInfo {
             });
           }
         },
-        visible: (node) => this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete: {
         method: (node, serviceModelId) => {
index 802047c..057cdd3 100644 (file)
@@ -14,6 +14,7 @@ import {DrawingBoardModes} from "../../../drawing-board.modes";
 import {AaiService} from "../../../../../shared/services/aaiService/aai.service";
 import {FeatureFlagsService} from "../../../../../shared/services/featureFlag/feature-flags.service";
 import {ITableContent} from "../../../../../shared/components/searchMembersModal/members-table/element-table-row.model";
+import {VNFModel} from "../../../../../shared/models/vnfModel";
 
 describe('VnfGroupingModelInfo Model Info', () => {
   let injector;
@@ -171,10 +172,7 @@ describe('VnfGroupingModelInfo Model Info', () => {
   });
 
   test('getModel should return VnfGroup model', () => {
-    let model: VnfGroupModel = vnfGroupModel.getModel('ResourceGroup0', <any>{
-      originalName : 'ResourceGroup0'
-    }, getServiceHierarchy());
-    expect(model.type).toEqual('VnfGroup');
+    expect(vnfGroupModel.getModel({})).toBeInstanceOf(VnfGroupModel);
   });
 
   test('getMenuAction: showAuditInfoVnfGroup', ()=>{
@@ -266,156 +264,5 @@ describe('VnfGroupingModelInfo Model Info', () => {
     ]);
   });
 
-  function getServiceHierarchy(){
-    return {
-      "service": {
-        "uuid": "6b528779-44a3-4472-bdff-9cd15ec93450",
-        "invariantUuid": "e49fbd11-e60c-4a8e-b4bf-30fbe8f4fcc0",
-        "name": "action-data",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "",
-        "serviceType": "",
-        "serviceRole": "",
-        "description": "",
-        "serviceEcompNaming": "false",
-        "instantiationType": "Macro",
-        "inputs": {
-          "2017488_pasqualevpe0_ASN": {
-            "type": "string",
-            "description": "AV/PE",
-            "entry_schema": null,
-            "inputProperties": null,
-            "constraints": [],
-            "required": true,
-            "default": "AV_vPE"
-          }
-        },
-        "vidNotions": {
-          "instantiationUI": "legacy",
-          "modelCategory": "other"
-        }
-      },
-      "vnfGroups": {
-        "ResourceGroup0": {
-          "type": "VnfGroup",
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "invariantUuid": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "version": "1",
-          "name": "ResourceGroup0",
-          "modelCustomizationName": "ResourceGroup0",
-          "properties": {
-            "contained_resource_type": "VF",
-            "role": "SERVICE-ACCESS",
-            "function": "DATA",
-            "description": "DDD0",
-            "type": "LOAD-GROUP"
-          },
-          "members": {
-            "vdorothea_svc_vprs_proxy 0": {
-              "uuid": "65fadfa8-a0d9-443f-95ad-836cd044e26c",
-              "invariantUuid": "f4baae0c-b3a5-4ca1-a777-afbffe7010bc",
-              "description": "A Proxy for Service vDOROTHEA_Svc_vPRS",
-              "name": "vDOROTHEA_Svc_vPRS Service Proxy",
-              "version": "1.0",
-              "customizationUuid": "bdb63d23-e132-4ce7-af2c-a493b4cafac9",
-              "inputs": {},
-              "commands": {},
-              "properties": {},
-              "type": "Service Proxy",
-              "sourceModelUuid": "da7827a2-366d-4be6-8c68-a69153c61274",
-              "sourceModelInvariant": "24632e6b-584b-4f45-80d4-fefd75fd9f14",
-              "sourceModelName": "vDOROTHEA_Svc_vPRS"
-            },
-            "vdorothea_svc_vprs_proxy 1": {
-              "uuid": "111dfa8-a0d9-443f-95ad-836cd044e26c",
-              "invariantUuid": "111ae0c-b3a5-4ca1-a777-afbffe7010bc",
-              "description": "A Proxy for Service vDOROTHEA_Svc_vPRS",
-              "name": "111_Svc_vPRS Service Proxy",
-              "version": "1.0",
-              "customizationUuid": "1113d23-e132-4ce7-af2c-a493b4cafac9",
-              "inputs": {},
-              "commands": {},
-              "properties": {},
-              "type": "Service Proxy",
-              "sourceModelUuid": "11127a2-366d-4be6-8c68-a69153c61274",
-              "sourceModelInvariant": "1112e6b-584b-4f45-80d4-fefd75fd9f14",
-              "sourceModelName": "111_Svc_vPRS"
-            }
-          }
-        }
-      },
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {},
-      "vfModules": {},
-      "volumeGroups": {},
-      "pnfs": {}
-    }
-  }
-
-  function loadMockMembers(): any[] {
-    return [
-      {
-        "action": "None",
-        "instanceName": "VNF1_INSTANCE_NAME",
-        "instanceId": "VNF1_INSTANCE_ID",
-        "orchStatus": null,
-        "productFamilyId": null,
-        "lcpCloudRegionId": "hvf23b",
-        "tenantId": "3e9a20a3e89e45f884e09df0cc2d2d2a",
-        "tenantName": "APPC-24595-T-IST-02C",
-        "modelInfo": {
-          "modelInvariantId": "vnf-instance-model-invariant-id",
-          "modelVersionId": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
-          "modelVersion": "2.0",
-          "modelName": "vf_vEPDG",
-          "modelType": "vnf"
-        },
-        "instanceType": "VNF1_INSTANCE_TYPE",
-        "provStatus": null,
-        "inMaint": false,
-        "uuid": "7a6ee536-f052-46fa-aa7e-2fca9d674c44",
-        "originalName": null,
-        "legacyRegion": null,
-        "lineOfBusiness": null,
-        "platformName": null,
-        "trackById": "7a6ee536-f052-46fa-aa7e-2fca9d674c44:002",
-        "serviceInstanceId": "service-instance-id1",
-        "serviceInstanceName": "service-instance-name"
-      },
-      {
-        "action": "None",
-        "instanceName": "VNF2_INSTANCE_NAME",
-        "instanceId": "VNF2_INSTANCE_ID",
-        "orchStatus": null,
-        "productFamilyId": null,
-        "lcpCloudRegionId": "hvf23b",
-        "tenantId": "3e9a20a3e89e45f884e09df0cc2d2d2a",
-        "tenantName": "APPC-24595-T-IST-02C",
-        "modelInfo": {
-          "modelInvariantId": "vnf-instance-model-invariant-id",
-          "modelVersionId": "eb5f56bf-5855-4e61-bd00-3e19a953bf02",
-          "modelVersion": "1.0",
-          "modelName": "vf_vEPDG",
-          "modelType": "vnf"
-        },
-        "instanceType": "VNF2_INSTANCE_TYPE",
-        "provStatus": null,
-        "inMaint": true,
-        "uuid": "eb5f56bf-5855-4e61-bd00-3e19a953bf02",
-        "originalName": null,
-        "legacyRegion": null,
-        "lineOfBusiness": null,
-        "platformName": null,
-        "trackById": "eb5f56bf-5855-4e61-bd00-3e19a953bf02:003",
-        "serviceInstanceId": "service-instance-id2",
-        "serviceInstanceName": "service-instance-name"
-      }
-    ];
-  }
-
 
 });
index 148ce22..2787c61 100644 (file)
@@ -83,21 +83,20 @@ export class VnfGroupingModelInfo implements ILevelNodeInfo {
 
   getType = (): string => 'VnfGroup';
 
-  createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string): any {
+  createInstanceTreeNode(instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any {
     let node = new VnfGroupTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node = this._sharedTreeService.addingStatusProperty(node);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node.limitMembers = (!_.isNil(model.properties.quantity)) ? model.properties.quantity : null;
     return node;
   }
 
-  getModel(modelId: string, instance: any, serviceHierarchy): any {
-    const originalModelName = instance.originalName ? instance.originalName : modelId;
-    return new VnfGroupModel(serviceHierarchy[this.name][originalModelName]);
+  getModel(instanceModel: any): any {
+    return new VnfGroupModel(instanceModel);
   }
 
   hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean): boolean {
@@ -275,8 +274,8 @@ export class VnfGroupingModelInfo implements ILevelNodeInfo {
             });
           }
         },
-        visible: (node) => this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete: {
         method: (node, serviceModelId) => {
index b951162..bc657ae 100644 (file)
@@ -29,17 +29,17 @@ export class VpnModelInfo implements ILevelNodeInfo {
 
   updateDynamicInputsDataFromModel = (currentModel): any => [];
 
-  getModel = (modelId: string, instance: any, serviceHierarchy): any => {
+  getModel = (instanceModel: any): any => {
     return new Level1Model();
   };
 
 
-  createInstanceTreeNode = (instance: NetworkInstance, model: any, parentModel, storeKey: string): VpnTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let node = new VpnTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node = this._sharedTreeService.addingStatusProperty(node);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     node = this._sharedTreeService.addingStatusProperty(node);
index 07d4cee..f3e479a 100644 (file)
@@ -32,6 +32,7 @@ describe('Vrf Model Info', () => {
   let _iframeService : IframeService;
   let _networkStepService : NetworkStepService;
   let _vpnStepService : VpnStepService;
+  let _featureFlagsService : FeatureFlagsService;
   let vrfModel: VrfModelInfo;
 
   beforeEach(() => {
@@ -59,11 +60,12 @@ describe('Vrf Model Info', () => {
     _dialogService = injector.get(DialogService);
     _iframeService = injector.get(IframeService);
     _networkStepService = injector.get(NetworkStepService);
+    _featureFlagsService = injector.get(FeatureFlagsService);
     _vpnStepService = injector.get(VpnStepService);
     _store = injector.get(NgRedux);
     _componentInfoService = injector.get(ComponentInfoService);
 
-    vrfModel = new VrfModelInfo(_store,_sharedTreeService, _dialogService, _iframeService, _networkStepService, _vpnStepService);
+    vrfModel = new VrfModelInfo(_store,_sharedTreeService, _dialogService, _iframeService, _featureFlagsService, _networkStepService, _vpnStepService);
 
   });
 
@@ -94,9 +96,16 @@ describe('Vrf Model Info', () => {
 
 
   test('getModel should return VRF model with min and max are equal to 1 (hard coded)', () => {
-    let model: VrfModel = vrfModel.getModel('VRF Entry Configuration 0', <any>{
-      originalName : 'VRF Entry Configuration 0'
-    }, getServiceHierarchy());
+    let model: VrfModel = vrfModel.getModel({
+        "uuid": "9cac02be-2489-4374-888d-2863b4511a59",
+        "invariantUuid": "b67a289b-1688-496d-86e8-1583c828be0a",
+        "properties": {
+          "ecomp_generated_naming": "false",
+          "type": "VRF-ENTRY",
+        },
+        "type": "Configuration"
+      }
+    );
     expect(model.properties['type']).toEqual('VRF-ENTRY');
     expect(model.min).toEqual(1);
     expect(model.max).toEqual(1);
@@ -159,80 +168,5 @@ describe('Vrf Model Info', () => {
     };
   }
 
-  function getServiceHierarchy() {
-    return {
-      "service": {
-        "uuid": "f028b2e2-7080-4b13-91b2-94944d4c42d8",
-        "invariantUuid": "dfc2c44c-2429-44ca-ae26-1e6dc1f207fb",
-        "name": "infraVPN",
-        "version": "1.0",
-        "toscaModelURL": null,
-        "category": "Network Service",
-        "serviceType": "BONDING",
-        "serviceRole": "INFRASTRUCTURE-VPN",
-        "description": "ddd",
-        "serviceEcompNaming": "true",
-        "instantiationType": "A-La-Carte",
-        "inputs": {},
-        "vidNotions": {
-          "instantiationUI": "macroService",
-          "modelCategory": "other",
-          "viewEditUI": "legacy"
-        }
-      },
-      "vnfs": {},
-      "networks": {},
-      "collectionResources": {},
-      "configurations": {},
-      "fabricConfigurations": {},
-      "serviceProxies": {
-        "misvpn_service_proxy 0": {
-          "uuid": "35186eb0-e6b6-4fa5-86bb-1501b342a7b1",
-          "invariantUuid": "73f89e21-b96c-473f-8884-8b93bcbd2f76",
-          "description": "A Proxy for Service MISVPN_SERVICE",
-          "name": "MISVPN_SERVICE Service Proxy",
-          "version": "3.0",
-          "customizationUuid": "4c2fb7e0-a0a5-4b32-b6ed-6a974e55d923",
-          "inputs": {},
-          "commands": {},
-          "properties": {
-            "ecomp_generated_naming": "false"
-          },
-          "type": "Service Proxy",
-          "sourceModelUuid": "d5cc7d15-c842-450e-95ae-2a69e66dd23b",
-          "sourceModelInvariant": "c126ec86-59fe-48c0-9532-e39a9b3e5272",
-          "sourceModelName": "MISVPN_SERVICE"
-        }
-      },
-      "vfModules": {},
-      "volumeGroups": {},
-      "pnfs": {},
-      "vnfGroups": {},
-      "vrfs": {
-        "VRF Entry Configuration 0": {
-          "uuid": "9cac02be-2489-4374-888d-2863b4511a59",
-          "invariantUuid": "b67a289b-1688-496d-86e8-1583c828be0a",
-          "description": "VRF Entry configuration object",
-          "name": "VRF Entry Configuration",
-          "version": "30.0",
-          "customizationUuid": "dd024d73-9bd1-425d-9db5-476338d53433",
-          "inputs": {},
-          "commands": {},
-          "properties": {
-            "ecomp_generated_naming": "false",
-            "type": "VRF-ENTRY",
-            "role": "INFRASTRUCTURE-CLOUD-VPN"
-          },
-          "type": "Configuration",
-          "modelCustomizationName": "VRF Entry Configuration 0",
-          "sourceNodes": [],
-          "collectorNodes": null,
-          "configurationByPolicy": false
-        }
-      }
-    }
-  }
-
-
 
 })
index 3dbc60a..53985d0 100644 (file)
@@ -3,7 +3,6 @@ import {ComponentInfoType} from "../../../component-info/component-info-model";
 import {ITreeNode} from "angular-tree-component/dist/defs/api";
 import {AvailableNodeIcons} from "../../../available-models-tree/available-models-tree.service";
 import {ModelInformationItem} from "../../../../../shared/components/model-information/model-information.component";
-import {VrfInstance} from "../../../../../shared/models/vrfInstance";
 import {VrfTreeNode} from "../../../../../shared/models/vrfTreeNode";
 import {VrfModel} from "../../../../../shared/models/vrfModel";
 import {NgRedux} from "@angular-redux/store";
@@ -50,17 +49,16 @@ export class VrfModelInfo implements ILevelNodeInfo {
 
   updateDynamicInputsDataFromModel = (currentModel): any => [];
 
-  getModel = (vrfModelId: string, instance: VrfInstance, serviceHierarchy): VrfModel => {
-    const originalModelName = instance.originalName ? instance.originalName : vrfModelId;
-    return new VrfModel(serviceHierarchy[this.name][originalModelName]);
+  getModel = (instanceModel: any): VrfModel => {
+    return new VrfModel(instanceModel);
   };
 
 
-  createInstanceTreeNode = (instance: VrfInstance, model: VrfModel, parentModel, storeKey: string): VrfTreeNode => {
+  createInstanceTreeNode = (instance: any, model: any, parentModel: any, storeKey: string, serviceModelId: string): any => {
     let node = new VrfTreeNode(instance, model, storeKey);
     node.missingData = this.hasMissingData(instance, node, model.isEcompGeneratedNaming);
     node.typeName = this.typeName;
-    node.menuActions = this.getMenuAction(<any>node, model.uuid);
+    node.menuActions = this.getMenuAction(<any>node, serviceModelId);
     node.isFailed = _.isNil(instance.isFailed) ? false : instance.isFailed;
     node.statusMessage = !_.isNil(instance.statusMessage) ? instance.statusMessage : "";
     return node;
@@ -111,7 +109,13 @@ export class VrfModelInfo implements ILevelNodeInfo {
     let counter: number = !_.isNil(this._store.getState().service.serviceInstance[serviceModelId]) ?
       (this._store.getState().service.serviceInstance[serviceModelId].existingVRFCounterMap[node.data.modelUniqueId] || 0) : 0;
     counter -= this._sharedTreeService.getExistingInstancesWithDeleteMode(node, serviceModelId, 'vrfs');
-    const model = node.data.getModel(node.data.name, node.data, serviceHierarchy);
+
+    const instanceModel = this._sharedTreeService.modelByIdentifiers(
+      serviceHierarchy, node.data.modelTypeName,
+      this._sharedTreeService.modelUniqueNameOrId(node.data), node.data.name
+    );
+
+    const model = node.data.getModel(instanceModel);
     const maxInstances: number = model.max;
     const isReachedLimit = !(maxInstances > counter);
     const showAddIcon = this._sharedTreeService.shouldShowAddIcon() && !isReachedLimit;
@@ -157,8 +161,8 @@ export class VrfModelInfo implements ILevelNodeInfo {
         method: (node, serviceModelId) => {
           this._store.dispatch(deleteActionVrfInstance(node.data.vrfStoreKey, serviceModelId));
         },
-        visible: (node) => this._sharedTreeService.shouldShowDelete(node),
-        enable: (node) => this._sharedTreeService.shouldShowDelete(node)
+        visible: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId),
+        enable: (node) => this._sharedTreeService.shouldShowDelete(node, serviceModelId)
       },
       undoDelete: {
         method: (node, serviceModelId) => {
index 1cec62b..5cf6e96 100644 (file)
@@ -27,13 +27,15 @@ import {VfModuleControlGenerator} from "../../../../shared/components/genericFor
 import {VnfGroupPopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service";
 import {VnfGroupControlGenerator} from "../../../../shared/components/genericForm/formControlsServices/vnfGroupGenerator/vnfGroup.control.generator";
 import {DuplicateService} from "../../duplicate/duplicate.service";
-import {SdcUiComponentsModule, SdcUiServices} from "onap-ui-angular";
+import {SdcUiComponentsModule} from "onap-ui-angular";
 import {ErrorMsgService} from "../../../../shared/components/error-msg/error-msg.service";
 import {ComponentInfoService} from "../../component-info/component-info.service";
 import {NetworkStepService} from "../models/vrf/vrfModal/networkStep/network.step.service";
 import {VpnStepService} from "../models/vrf/vrfModal/vpnStep/vpn.step.service";
 import {VfModuleUpgradePopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 import {SharedControllersService} from "../../../../shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../../shared/components/customModal/services/modal.service";
+import {CreateDynamicComponentService} from "../../../../shared/components/customModal/services/create-dynamic-component.service";
 
 class MockAppStore<T> {
   getState() {
@@ -86,9 +88,11 @@ describe('Model Tree Generator service', () => {
         DialogService,
         ErrorMsgService,
         ComponentInfoService,
-        SdcUiServices.ModalService,
+        ModalService,
         NetworkStepService,
         VpnStepService,
+        ModalService,
+        CreateDynamicComponentService,
         { provide: NgRedux, useClass: MockAppStore },
         MockNgRedux]
     });
@@ -2462,7 +2466,6 @@ describe('Model Tree Generator service', () => {
           "tenantId": "229bcdc6eaeb4ca59d55221141d01f8e",
           "platformName": "xxx1",
           "lineOfBusiness": "ONAP",
-          "uuid": "network-instance-model-version-id",
           "routeTarget": {
             "globalRouteTarget": "mock-global-1",
             "routeTargetRole": "mock-role-x"
@@ -2583,6 +2586,7 @@ describe('Model Tree Generator service', () => {
       {
         "action": 'None',
         "modelId": "afacccf6-397d-45d6-b5ae-94c39734b168",
+        "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
         "modelCustomizationId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
         "modelUniqueId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
         "missingData": true,
@@ -2592,6 +2596,7 @@ describe('Model Tree Generator service', () => {
         "inMaint": true,
         "name": "2017-388_PASQUALE-vPE 0",
         "modelName": "2017-388_PASQUALE-vPE 0",
+        "modelTypeName": "vnfs",
         "type": "VF",
         "parentType": '',
         "isEcompGeneratedNaming": false,
@@ -2619,6 +2624,7 @@ describe('Model Tree Generator service', () => {
         "parentType": '',
         "name": "2017-488_PASQUALE-vPE 0",
         "modelName": "2017-488_PASQUALE-vPE 0",
+        "modelTypeName": "vnfs",
         "type": "VF",
         "isEcompGeneratedNaming": false,
         "networkStoreKey": "2017-488_PASQUALE-vPE 0",
@@ -2633,6 +2639,7 @@ describe('Model Tree Generator service', () => {
           "parentType": 'VNF',
           "action": 'None',
           "modelId": "f8360508-3f17-4414-a2ed-6bc71161e8db",
+          "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091",
           "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
           "modelUniqueId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
           "missingData": true,
@@ -2640,6 +2647,7 @@ describe('Model Tree Generator service', () => {
           "statusMessage": "Failed vfModel message",
           "name": "&lt;Automatically Assigned&gt;",
           "modelName": "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
+          "modelTypeName": "vfModules",
           "type": "VFmodule",
           "isEcompGeneratedNaming": false,
           "dynamicInputs": [],
@@ -2664,6 +2672,7 @@ describe('Model Tree Generator service', () => {
         "id": "o65b26t2thj",
         "name": "2017488_PASQUALEvPE",
         "modelName": "2017-488_PASQUALE-vPE 0",
+        "modelTypeName": "vnfs",
         "type": "VF",
         "isEcompGeneratedNaming": false,
         "vnfStoreKey": "2017-488_PASQUALE-vPE 0",
@@ -2680,6 +2689,7 @@ describe('Model Tree Generator service', () => {
             "missingData": false,
             "name": "yoav",
             "modelName": "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
+            "modelTypeName": "vfModules",
             "type": "VFmodule",
             "isEcompGeneratedNaming": false,
             "typeName": "M",
@@ -2733,6 +2743,7 @@ describe('Model Tree Generator service', () => {
         "parentType": '',
         "action": 'None',
         "modelId": "ddc3f20c-08b5-40fd-af72-c6d14636b986",
+        "modelInvariantId": "379f816b-a7aa-422f-be30-17114ff50b7c",
         "modelCustomizationId": "94fdd893-4a36-4d70-b16a-ec29c54c184f",
         "modelUniqueId": "94fdd893-4a36-4d70-b16a-ec29c54c184f",
         "missingData": false,
@@ -2742,6 +2753,7 @@ describe('Model Tree Generator service', () => {
         "routeTargetRole": "mock-role-x",
         "statusMessage": "Network failed message",
         "modelName": "ExtVL 0",
+        "modelTypeName": "networks",
         "type": "VL",
         "isEcompGeneratedNaming": true,
         "networkStoreKey": "ExtVL 0",
@@ -2761,6 +2773,7 @@ describe('Model Tree Generator service', () => {
         "id": "2mdxioxca9h",
         "name": "&lt;Automatically Assigned&gt;",
         "modelName": "ExtVL 0",
+        "modelTypeName": "networks",
         "type": "VL",
         "isEcompGeneratedNaming": true,
         "networkStoreKey": "ExtVL 0:0001",
@@ -2775,6 +2788,7 @@ describe('Model Tree Generator service', () => {
         "id": "z7vd1gmpbs",
         "name": "ExtVL",
         "modelName": "ExtVL 0",
+        "modelTypeName": "networks",
         "type": "VL",
         "isEcompGeneratedNaming": true,
         "networkStoreKey": "ExtVL 0_1",
index 8ddb4ba..13dca56 100644 (file)
@@ -8,10 +8,12 @@ import {ErrorMsgService} from "../../../../shared/components/error-msg/error-msg
 import {FeatureFlagsService, Features} from "../../../../shared/services/featureFlag/feature-flags.service";
 import {NgRedux} from "@angular-redux/store";
 import {AppState} from "../../../../shared/store/reducers";
+import {SharedTreeService} from "../shared.tree.service";
 
 @Injectable()
 export class ObjectToInstanceTreeService {
-  constructor(private _objectToTreeService: ObjectToTreeService, private _errorMsgService: ErrorMsgService, private store: NgRedux<AppState>) {
+  constructor(private _objectToTreeService: ObjectToTreeService, private _errorMsgService: ErrorMsgService,
+              private store: NgRedux<AppState>, private _sharedTreeService: SharedTreeService) {
     this.numberOfFailed = 0;
     this.numberOfElements = 0;
 
@@ -34,10 +36,11 @@ export class ObjectToInstanceTreeService {
     this.numberOfFailed = 0;
     this.numberOfElements = 0;
     let _this = this;
+    const serviceModelId:string = serviceInstance.modelInfo.modelVersionId;
     const firstLevelOptions: ILevelNodeInfo[] = _this._objectToTreeService.getFirstLevelOptions();
     for (let option of firstLevelOptions) {
       _.forOwn(serviceInstance[option.name], function (instance, modelName) {
-        nodes.push(_this.getNodeInstance(modelName, null, instance, serviceHierarchy, option));
+        nodes.push(_this.getNodeInstance(modelName, null, instance, serviceHierarchy, option, serviceModelId));
       });
     }
     return this.sortElementsByPosition(nodes);
@@ -71,18 +74,23 @@ export class ObjectToInstanceTreeService {
    * @param instance
    * @param serviceHierarchy - The service Hierarchy store
    * @param option
+   * @param serviceModelId
    * @param parentType
    ****************************************************************/
-  getNodeInstance(modelName: string, parentModel: any, instance: any, serviceHierarchy, option: ILevelNodeInfo, parentType ?: string) {
-    const model = option.getModel(modelName, instance, serviceHierarchy);
-
-    let optionalNodes = option.createInstanceTreeNode(instance, model, parentModel, modelName);
+  getNodeInstance(modelName: string, parentModel: any, instance: any, serviceHierarchy, option: ILevelNodeInfo, serviceModelId: string, parentType ?: string) {
+    const instanceModel = this._sharedTreeService.modelByIdentifiers(
+      serviceHierarchy, option.name,
+      this._sharedTreeService.modelUniqueNameOrId(instance), modelName
+    );
+    const model = option.getModel(instanceModel);
+
+    let optionalNodes = option.createInstanceTreeNode(instance, model, parentModel, modelName, serviceModelId);
     this.increaseNumberOfFailed(optionalNodes);
     this.increaseNumberOfExcitingElements();
     let nodes: any[] = _.isArray(optionalNodes) ? optionalNodes : [optionalNodes];
     for (let node of nodes) {
       node = this.addingExtraDataToNode(node, modelName, parentModel, instance, serviceHierarchy, option, parentType);
-      let children = this.addNextInstanceTreeNode(instance, model, option, node, serviceHierarchy);
+      let children = this.addNextInstanceTreeNode(instance, model, option, node, serviceHierarchy, serviceModelId);
       if (!_.isNil(children) && children.length > 0) {
         node.children = this.sortElementsByPosition(children);
       }
@@ -97,6 +105,7 @@ export class ObjectToInstanceTreeService {
       node.parentType = !_.isNil(parentType) ? parentType : "";
       node.updatePoistionFunction = option.updatePosition;
       node.position = option.getNodePosition(instance, node.dynamicModelName);
+      node.modelTypeName = option.name;
       node.getModel = option.getModel.bind(option);
       node.getInfo = !_.isNil(option.getInfo) ? option.getInfo.bind(option) : ()=>{};
       node.componentInfoType = option.componentInfoType;
@@ -119,8 +128,9 @@ export class ObjectToInstanceTreeService {
    * @param levelNodeInfo
    * @param parentNode
    * @param serviceHierarchy - The service Hierarchy store
+   * @param serviceModelId
    ****************************************************************/
-  addNextInstanceTreeNode(parentInstance, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, serviceHierarchy): any[] {
+  addNextInstanceTreeNode(parentInstance, parentModel, levelNodeInfo: ILevelNodeInfo, parentNode, serviceHierarchy, serviceModelId: string): any[] {
     if (!_.isNil(levelNodeInfo.childNames)&& levelNodeInfo.childNames.length > 0) {
       const that = this;
       parentNode.children = [];
@@ -130,7 +140,7 @@ export class ObjectToInstanceTreeService {
           let nextLevelNodeInfo = levelNodeInfo.getNextLevelObject.apply(that, [childName]);
           Object.keys(parentInstance[childName]).map((modelName) => {
             let nextLevelInstance = parentInstance[childName][modelName];
-            let nodes: any[] | any = that.getNodeInstance(modelName, parentModel, nextLevelInstance, serviceHierarchy, nextLevelNodeInfo, parentType);
+            let nodes: any[] | any = that.getNodeInstance(modelName, parentModel, nextLevelInstance, serviceHierarchy, nextLevelNodeInfo, serviceModelId, parentType);
             if (_.isArray(nodes)) {
               parentNode.children = parentNode.children.concat(nodes);
             } else {
index 0f7bf9a..7fa679b 100644 (file)
@@ -37,6 +37,8 @@ import {VpnStepService} from "../models/vrf/vrfModal/vpnStep/vpn.step.service";
 import {NetworkStepService} from "../models/vrf/vrfModal/networkStep/network.step.service";
 import {VfModuleUpgradePopupService} from "../../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 import {SharedControllersService} from "../../../../shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../../shared/components/customModal/services/modal.service";
+import {CreateDynamicComponentService} from "../../../../shared/components/customModal/services/create-dynamic-component.service";
 
 class MockAppStore<T> {
   getState() {
@@ -112,6 +114,8 @@ describe('Model Tree Generator service', () => {
         ComponentInfoService,
         NetworkStepService,
         VpnStepService,
+        ModalService,
+        CreateDynamicComponentService,
         SharedControllersService,
         {provide: NgRedux, useClass: MockAppStore},
         MockNgRedux ]
@@ -207,6 +211,7 @@ describe('Model Tree Generator service', () => {
       "name": "2017-388_PASQUALE-vPE 1",
       "tooltip": "VF",
       "type": "VF",
+      "modelTypeName": "vnfs",
       "count": 0,
       "max": 1,
       "children": [],
@@ -224,6 +229,7 @@ describe('Model Tree Generator service', () => {
       "name": "2017-388_PASQUALE-vPE 0",
       "tooltip": "VF",
       "type": "VF",
+      "modelTypeName": "vnfs",
       "count": 0,
       "max": 1,
       "children": [],
@@ -239,6 +245,7 @@ describe('Model Tree Generator service', () => {
       "name": "2017-488_PASQUALE-vPE 0",
       "tooltip": "VF",
       "type": "VF",
+      "modelTypeName": "vnfs",
       "count": 0,
       "max": 1,
       "children": [{
@@ -249,6 +256,7 @@ describe('Model Tree Generator service', () => {
         "name": "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1",
         "tooltip": "VFmodule",
         "type": "VFmodule",
+        "modelTypeName": "vfModules",
         "count": 0,
         "max": 1,
         "children": [],
@@ -264,6 +272,7 @@ describe('Model Tree Generator service', () => {
         "name": "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
         "tooltip": "VFmodule",
         "type": "VFmodule",
+        "modelTypeName": "vfModules",
         "count": 0,
         "max": 1,
         "children": [],
@@ -279,6 +288,7 @@ describe('Model Tree Generator service', () => {
         "name": "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vPFE_BV..module-2",
         "tooltip": "VFmodule",
         "type": "VFmodule",
+        "modelTypeName": "vfModules",
         "count": 0,
         "max": 1,
         "children": [],
index f1ebdaf..c3c8fa1 100644 (file)
@@ -121,11 +121,11 @@ export class ObjectToModelTreeService {
     node.getNodeCount = (node, serviceId) => levelNodeInfo.getNodeCount(node, serviceId);
     node.getMenuAction = (node, serviceId) => levelNodeInfo.getMenuAction(node, serviceId);
     node.showNodeIcons = (node, serviceId) => levelNodeInfo.showNodeIcons(node, serviceId);
-    node.typeName = levelNodeInfo.typeName;
     node.getModel = levelNodeInfo.getModel.bind(levelNodeInfo);
-    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : () => {
-    };
+    node.getInfo = !_.isNil(levelNodeInfo.getInfo) ? levelNodeInfo.getInfo.bind(levelNodeInfo) : () => {};
     node.componentInfoType = levelNodeInfo.componentInfoType;
+    node.typeName = levelNodeInfo.typeName;
+    node.modelTypeName = levelNodeInfo.name;
     return node;
   }
 }
index 9b68627..a70b7ef 100644 (file)
@@ -15,7 +15,6 @@ import {VfModulePopupService} from "../../../shared/components/genericFormPopup/
 import {VnfGroupingModelInfo} from "./models/vnfGrouping/vnfGrouping.model.info";
 import {VnfGroupPopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vnfGroup/vnfGroup.popup.service";
 import {DuplicateService} from "../duplicate/duplicate.service";
-import {SdcUiServices} from "onap-ui-angular";
 import {IframeService} from "../../../shared/utils/iframe.service";
 import {ComponentInfoService} from "../component-info/component-info.service";
 import {PnfModelInfo} from "./models/pnf/pnf.model.info";
@@ -24,8 +23,9 @@ import {AaiService} from "../../../shared/services/aaiService/aai.service";
 import {VrfModelInfo} from "./models/vrf/vrf.model.info";
 import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service";
 import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service";
-import { VfModuleUpgradePopupService } from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
+import {VfModuleUpgradePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 import {FeatureFlagsService} from "../../../shared/services/featureFlag/feature-flags.service";
+import {ModalService} from "../../../shared/components/customModal/services/modal.service";
 
 @Injectable()
 export class ObjectToTreeService {
@@ -39,7 +39,7 @@ export class ObjectToTreeService {
               private _vfModuleUpgradePopupService : VfModuleUpgradePopupService,
               private _vnfGroupPopupService : VnfGroupPopupService,
               private _duplicateService : DuplicateService,
-              private _modalService: SdcUiServices.ModalService,
+              private _modalService: ModalService,
               private _iframeService : IframeService,
               private _componentInfoService : ComponentInfoService,
               private _networkStepService : NetworkStepService,
@@ -50,15 +50,13 @@ export class ObjectToTreeService {
   }
 
 
-
-
   /***********************************************************
    * return all first optional first level of the model tree
    ************************************************************/
   getFirstLevelOptions(): ILevelNodeInfo[] {
     return [new VnfModelInfo(this._dynamicInputsService, this._sharedTreeService, this._defaultDataGeneratorService, this._dialogService, this._vnfPopupService, this._vfModulePopupService, this._vfModuleUpgradePopupService,this._duplicateService, this._modalService, this._iframeService, this._componentInfoService, this._featureFlagsService, this._store)
       , new NetworkModelInfo(this._dynamicInputsService, this._sharedTreeService, this._dialogService, this._networkPopupService, this._duplicateService, this._modalService, this._iframeService,  this._featureFlagsService, this._store),
-      new PnfModelInfo(),
+      new PnfModelInfo(this._sharedTreeService),
       new VrfModelInfo(this._store, this._sharedTreeService, this._dialogService, this._iframeService, this._featureFlagsService, this._networkStepService, this._vpnStepService),
       new CollectionResourceModelInfo(this._store, this._sharedTreeService),
       new ConfigurationModelInfo(this._dynamicInputsService, this._sharedTreeService),
index 3a65b93..8905d41 100644 (file)
@@ -42,6 +42,8 @@ import {VpnStepService} from "./models/vrf/vrfModal/vpnStep/vpn.step.service";
 import {NetworkStepService} from "./models/vrf/vrfModal/networkStep/network.step.service";
 import {VfModuleUpgradePopupService} from "../../../shared/components/genericFormPopup/genericFormServices/vfModuleUpgrade/vfModule.upgrade.popuop.service";
 import {SharedControllersService} from "../../../shared/components/genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../shared/components/customModal/services/modal.service";
+import {CreateDynamicComponentService} from "../../../shared/components/customModal/services/create-dynamic-component.service";
 
 class MockAppStore<T> {
   getState() {
@@ -61,7 +63,7 @@ function getNodeWithData(menuAction:string){
   };
   nodeData['menuActions'][menuAction] =  {
     method: (node, serviceModelId) => {}
-  }
+  };
   const node = {
     parent: {
       data: nodeData,
@@ -114,6 +116,8 @@ describe('Shared Tree Service', () => {
         ComponentInfoService,
         NetworkStepService,
         VpnStepService,
+        ModalService,
+        CreateDynamicComponentService,
         {provide: NgRedux, useClass: MockAppStore}
       ]
     });
@@ -130,7 +134,7 @@ describe('Shared Tree Service', () => {
 
   test('SharedTreeService upgradeBottomUp should call redux actions', () => {
     const serviceModelId = "1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd";
-    const node = getNodeWithData("upgrade")
+    const node = getNodeWithData("upgrade");
     spyOn(node.parent.data.menuActions['upgrade'], 'method');
     service.upgradeBottomUp(node, serviceModelId);
     expect(node.parent.data.menuActions['upgrade'].method).toBeCalledWith(node.parent, serviceModelId);
@@ -140,7 +144,7 @@ describe('Shared Tree Service', () => {
 
   test('SharedTreeService undoUpgradeBottomUp should call redux actions', () => {
     const serviceModelId = "1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd";
-    const node = getNodeWithData("undoUpgrade")
+    const node = getNodeWithData("undoUpgrade");
     spyOn(node.parent.data.menuActions['undoUpgrade'], 'method');
     service.undoUpgradeBottomUp(node, serviceModelId);
     expect(node.parent.data.menuActions['undoUpgrade'].method).toBeCalledWith(node.parent, serviceModelId);
@@ -162,7 +166,37 @@ describe('Shared Tree Service', () => {
     expect(MessageBoxService.openModal.next).toHaveBeenCalled();
   });
 
-  test('openAuditInfoModal should open modal for failed instance', () => {
+  each([
+    ['volumeGroups by entry name', "volumeGroups",
+      "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_vRE_BV..module-1", "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1"],
+    ['vfmodule by customizationUuid', "vfModules",
+      "f7e7c365-60cf-49a9-9ebf-a1aa11b9d401", "2017488PasqualeVpe..PASQUALE_vRE_BV..module-1"],
+    ['vnf by customizationUuid', "vnfs",
+      "1da7b585-5e61-4993-b95e-8e6606c81e45", "2017-488_PASQUALE-vPE 0"],
+    ['vnfGroups by invariantUuid because no customizationUuid', "vnfGroups",
+      "4bb2e27e-ddab-4790-9c6d-1f731bc14a45", "groupingservicefortest..ResourceInstanceGroup..0"],
+  ]).test('modelByIdentifier should success: %s', (description, modelTypeName, modelUniqueIdOrName, expectedModelCustomizationName) => {
+    let serviceModelFromHierarchy =
+      getStore().service.serviceHierarchy["1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"];
+
+    expect(service.modelByIdentifiers(serviceModelFromHierarchy, modelTypeName, modelUniqueIdOrName))
+      .toHaveProperty("modelCustomizationName", expectedModelCustomizationName);
+  });
+
+  each([
+    ['vfmodule by invariantUuid when there is customizationUuid', "vfModules", "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1"],
+    ['network by non-existing modelUniqueIdOrName', "networks", "7253ff5c-97f0-4b8b-937c-77aeb4d79aa1"],
+    ['collectionResource has no resource', "collectionResources", "whatever"],
+    ['non-existing model-type', "fooBar", "whatever"],
+  ]).test('modelByIdentifier should fail: %s', (description, modelTypeName, modelUniqueIdOrName) => {
+    let serviceModelFromHierarchy =
+      getStore().service.serviceHierarchy["1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"];
+
+    expect(service.modelByIdentifiers(serviceModelFromHierarchy, modelTypeName, modelUniqueIdOrName))
+      .toBeUndefined();
+  });
+
+  test('openAuditInfoModalInsideIframe should open modal for failed instance', () => {
     jest.spyOn(AuditInfoModalComponent.openInstanceAuditInfoModal, 'next');
 
     let modelInfoServiceMock: ILevelNodeInfo = new VnfModelInfo(null, null,
@@ -230,7 +264,6 @@ describe('Shared Tree Service', () => {
   });
 
 
-
   test('statusProperties should be prop on node according to node properties', () => {
     let node = service.addingStatusProperty({orchStatus: 'completed', provStatus: 'inProgress', inMaint: false});
     expect(node.statusProperties).toBeDefined();
@@ -250,6 +283,39 @@ describe('Shared Tree Service', () => {
       testId: 'inMaint'
     })]);
   });
+
+  each([
+    [false, 'method is not in menu actions', ServiceInstanceActions.None, DrawingBoardModes.EDIT, {}, true],
+    [false, 'there is no action in node', null, DrawingBoardModes.EDIT, {someMethod: "someValue"}, true],
+    [true, 'edit mode, action is none, method in menu action', ServiceInstanceActions.None, DrawingBoardModes.EDIT, {someMethod: "someValue"}, true],
+    [false, 'edit mode, action is none, method in menu action, macro service', ServiceInstanceActions.None, DrawingBoardModes.EDIT, {someMethod: "someValue"}, false],
+    [false, 'edit mode, action is not none, method in menu action', ServiceInstanceActions.Resume, DrawingBoardModes.EDIT, {someMethod: "someValue"}, true],
+    [false, 'edit mode, action is CREATE, method in menu action', ServiceInstanceActions.Resume, DrawingBoardModes.EDIT, {someMethod: "someValue"}, true]
+  ]).test('shouldShowButtonGeneric return %s if %s ', (expected, description, action, mode, menuActions, isALaCarte) => {
+    jest.spyOn(store, 'getState').mockReturnValue(<any>{
+      global: {
+        drawingBoardStatus: mode
+      },
+      service : {
+        serviceInstance: {
+          someModelId : {
+            isALaCarte
+          }
+        }
+
+      }
+    });
+    let node = <any>{
+      data:{
+        action: action,
+        menuActions: menuActions
+      },
+    };
+
+    let res = service.shouldShowButtonGeneric(node, "someMethod", "someModelId");
+    expect(res).toBe(expected);
+  });
+
   const enableRemoveAndEditItemsDataProvider = [
     ['Create action CREATE mode', DrawingBoardModes.CREATE ,ServiceInstanceActions.Create, true],
     ['Create action VIEW mode',DrawingBoardModes.VIEW , ServiceInstanceActions.Create,false],
@@ -272,205 +338,61 @@ describe('Shared Tree Service', () => {
       let res = service.shouldShowRemoveAndEdit(node);
       expect(res).toBe(enabled);
     });
-});
-function generateService() {
-  return {
-    "vnfs": {
-      "2017-488_PASQUALE-vPE 0": {
-        "inMaint": false,
-        "rollbackOnFailure": "true",
-        "originalName": "2017-488_PASQUALE-vPE 0",
-        "isMissingData": false,
-        "trackById": "stigekyxrqi",
-        "vfModules": {
-          "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0": {
-            "2017488_pasqualevpe0..2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0gytfi": {
-              "isMissingData": false,
-              "sdncPreReload": null,
-              "modelInfo": {
-                "modelType": "VFmodule",
-                "modelInvariantId": "b34833bb-6aa9-4ad6-a831-70b06367a091",
-                "modelVersionId": "f8360508-3f17-4414-a2ed-6bc71161e8db",
-                "modelName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0",
-                "modelVersion": "5",
-                "modelCustomizationId": "a55961b2-2065-4ab0-a5b7-2fcee1c227e3",
-                "modelCustomizationName": "2017488PasqualeVpe..PASQUALE_base_vPE_BV..module-0"
-              },
-              "instanceParams": [{}],
-              "trackById": "3oj23o7nupo"
+
+
+  const isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDifferProvider = [
+    ['node is part of model, but vfmodule diff by customization',
+      true, 'mDNS 01222020 0', '9fdc68e9-9f53-431c-b8a2-7e337b9a0d0a', '82160e6e-d9c4-45ef-bd19-01573ab11b61'],
+
+    ['vnf model-name not found',
+      false, 'mDNS 01222020 1', '9fdc68e9-9f53-431c-b8a2-7e337b9a0d0a', '82160e6e-d9c4-45ef-bd19-01573ab11b61'],
+
+    ['vfmodule invariant-id not found',
+      false, 'mDNS 01222020 0', 'wrong invariant-id', '82160e6e-d9c4-45ef-bd19-01573ab11b61'],
+
+    ['vfmodule customization-id match',
+      false, 'mDNS 01222020 0', '9fdc68e9-9f53-431c-b8a2-7e337b9a0d0a', 'c9b32003-febc-44e0-a97f-7630fa7fa4a0'],
+  ];
+
+  each(isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDifferProvider).test('isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDiffer: when  %s should return %s', (description, expected, vnfModelName, invariantUuid, customizationUuid) => {
+    const serviceModelId : string = 'a243da28-c11e-45a8-9f26-0284a9a789bc';
+    spyOn(store, 'getState').and.returnValue({
+      service : {
+        serviceHierarchy : {
+          [serviceModelId] : {
+            vnfs : {
+              [vnfModelName] : {
+                vfModules : {
+                  vfModuleModelName : {
+                    invariantUuid : invariantUuid,
+                    customizationUuid : customizationUuid
+                  }
+                }
+              }
             }
           }
-        },
-        "vnfStoreKey": "2017-488_PASQUALE-vPE 0",
-        "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-        "productFamilyId": "d8a6ed93-251c-47ca-adc9-86671fd19f4c",
-        "lcpCloudRegionId": "AAIAIC25",
-        "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
-        "lineOfBusiness": "ONAP",
-        "platformName": "xxx1",
-        "modelInfo": {
-          "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "modelVersionId": "69e09f68-8b63-4cc9-b9ff-860960b5db09",
-          "modelName": "2017-488_PASQUALE-vPE",
-          "modelVersion": "5.0",
-          "modelCustomizationName": "2017-488_PASQUALE-vPE 0",
-          "modelCustomizationId": "1da7b585-5e61-4993-b95e-8e6606c81e45",
-          "uuid": "69e09f68-8b63-4cc9-b9ff-860960b5db09"
-        },
-        "legacyRegion": "11111111",
-        "instanceParams": [{}]
-      },
-      "2017-388_PASQUALE-vPE 0": {
-        "inMaint": false,
-        "rollbackOnFailure": "true",
-        "originalName": "2017-388_PASQUALE-vPE 0",
-        "isMissingData": false,
-        "trackById": "nib719t5vca",
-        "vfModules": {},
-        "vnfStoreKey": "2017-388_PASQUALE-vPE 0",
-        "productFamilyId": "d8a6ed93-251c-47ca-adc9-86671fd19f4c",
-        "lcpCloudRegionId": "AAIAIC25",
-        "legacyRegion": "11111",
-        "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
-        "platformName": "platform",
-        "lineOfBusiness": "zzz1",
-        "instanceParams": [{}],
-        "modelInfo": {
-          "modelInvariantId": "72e465fe-71b1-4e7b-b5ed-9496118ff7a8",
-          "modelVersionId": "afacccf6-397d-45d6-b5ae-94c39734b168",
-          "modelName": "2017-388_PASQUALE-vPE",
-          "modelVersion": "4.0",
-          "modelCustomizationId": "b3c76f73-eeb5-4fb6-9d31-72a889f1811c",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 0",
-          "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168"
-        },
-        "uuid": "afacccf6-397d-45d6-b5ae-94c39734b168"
-      },
-      "2017-388_PASQUALE-vPE 1": {
-        "inMaint": false,
-        "rollbackOnFailure": "true",
-        "originalName": "2017-388_PASQUALE-vPE 1",
-        "isMissingData": false,
-        "trackById": "cv7l1ak8vpe",
-        "vfModules": {},
-        "vnfStoreKey": "2017-388_PASQUALE-vPE 1",
-        "productFamilyId": "d8a6ed93-251c-47ca-adc9-86671fd19f4c",
-        "lcpCloudRegionId": "AAIAIC25",
-        "legacyRegion": "123",
-        "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
-        "platformName": "platform",
-        "lineOfBusiness": "ONAP",
-        "instanceParams": [{}],
-        "modelInfo": {
-          "modelInvariantId": "00beb8f9-6d39-452f-816d-c709b9cbb87d",
-          "modelVersionId": "0903e1c0-8e03-4936-b5c2-260653b96413",
-          "modelName": "2017-388_PASQUALE-vPE",
-          "modelVersion": "1.0",
-          "modelCustomizationId": "280dec31-f16d-488b-9668-4aae55d6648a",
-          "modelCustomizationName": "2017-388_PASQUALE-vPE 1",
-          "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413"
-        },
-        "uuid": "0903e1c0-8e03-4936-b5c2-260653b96413"
-      }
-    },
-    "instanceParams": [{}],
-    "validationCounter": 0,
-    "existingNames": {"yoav": ""},
-    "existingVNFCounterMap": {
-      "69e09f68-8b63-4cc9-b9ff-860960b5db09": 1,
-      "afacccf6-397d-45d6-b5ae-94c39734b168": 1,
-      "0903e1c0-8e03-4936-b5c2-260653b96413": 1
-    },
-    "existingVnfGroupCounterMap": {
-      "daeb6568-cef8-417f-9075-ed259ce59f48": 0,
-      "c2b300e6-45de-4e5e-abda-3032bee2de56": -1
-    },
-    "existingNetworksCounterMap": {"ddc3f20c-08b5-40fd-af72-c6d14636b986": 1},
-    "networks": {
-      "ExtVL 0": {
-        "inMaint": false,
-        "rollbackOnFailure": "true",
-        "originalName": "ExtVL 0",
-        "isMissingData": false,
-        "trackById": "s6okajvv2n8",
-        "networkStoreKey": "ExtVL 0",
-        "productFamilyId": "d8a6ed93-251c-47ca-adc9-86671fd19f4c",
-        "lcpCloudRegionId": "AAIAIC25",
-        "legacyRegion": "12355555",
-        "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
-        "platformName": "platform",
-        "lineOfBusiness": null,
-        "instanceParams": [{}],
-        "modelInfo": {
-          "modelInvariantId": "379f816b-a7aa-422f-be30-17114ff50b7c",
-          "modelVersionId": "ddc3f20c-08b5-40fd-af72-c6d14636b986",
-          "modelName": "ExtVL",
-          "modelVersion": "37.0",
-          "modelCustomizationId": "94fdd893-4a36-4d70-b16a-ec29c54c184f",
-          "modelCustomizationName": "ExtVL 0",
-          "uuid": "ddc3f20c-08b5-40fd-af72-c6d14636b986"
-        },
-        "uuid": "ddc3f20c-08b5-40fd-af72-c6d14636b986"
+        }
       }
-    },
-    "vnfGroups": {
-      "groupingservicefortest..ResourceInstanceGroup..0": {
-        "inMaint": false,
-        "rollbackOnFailure": "true",
-        "originalName": "groupingservicefortest..ResourceInstanceGroup..0",
-        "isMissingData": false,
-        "trackById": "se0obn93qq",
-        "vnfGroupStoreKey": "groupingservicefortest..ResourceInstanceGroup..0",
-        "instanceName": "groupingservicefortestResourceInstanceGroup0",
-        "instanceParams": [{}],
-        "modelInfo": {
-          "modelInvariantId": "4bb2e27e-ddab-4790-9c6d-1f731bc14a45",
-          "modelVersionId": "daeb6568-cef8-417f-9075-ed259ce59f48",
-          "modelName": "groupingservicefortest..ResourceInstanceGroup..0",
-          "modelVersion": "1",
-          "modelCustomizationName": "groupingservicefortest..ResourceInstanceGroup..0",
-          "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48"
-        },
-        "uuid": "daeb6568-cef8-417f-9075-ed259ce59f48"
+    });
+
+    const node = <any>{
+      data:{
+        modelInvariantId : '9fdc68e9-9f53-431c-b8a2-7e337b9a0d0a',
+        modelCustomizationId : 'c9b32003-febc-44e0-a97f-7630fa7fa4a0',
+        modelName : 'vfModuleModelName'
+      },
+      parent : {
+        data : {
+          modelName : "mDNS 01222020 0"
+        }
       }
-    },
-    "instanceName": "yoav",
-    "globalSubscriberId": "e433710f-9217-458d-a79d-1c7aff376d89",
-    "subscriptionServiceType": "TYLER SILVIA",
-    "owningEntityId": "d61e6f2d-12fa-4cc2-91df-7c244011d6fc",
-    "productFamilyId": "d8a6ed93-251c-47ca-adc9-86671fd19f4c",
-    "lcpCloudRegionId": "AAIAIC25",
-    "tenantId": "092eb9e8e4b7412e8787dd091bc58e86",
-    "aicZoneId": "ATL53",
-    "pause": null,
-    "projectName": "WATKINS",
-    "rollbackOnFailure": "true",
-    "bulkSize": 1,
-    "aicZoneName": "AAIATLTE-ATL53",
-    "owningEntityName": "WayneHolland",
-    "testApi": "VNF_API",
-    "isEcompGeneratedNaming": false,
-    "tenantName": "USP-SIP-IC-24335-T-01",
-    "modelInfo": {
-      "modelInvariantId": "cdb90b57-ed78-4d44-a5b4-7f43a02ec632",
-      "modelVersionId": "1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd",
-      "modelName": "action-data",
-      "modelVersion": "1.0",
-      "uuid": "1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd"
-    },
-    "isALaCarte": false,
-    "name": "action-data",
-    "version": "1.0",
-    "description": "PASQUALE vMX vPE based on Juniper 17.2 release. Updated with updated VF for v8.0 of VLM",
-    "category": "Network L1-3",
-    "uuid": "1a80c596-27e5-4ca9-b5bb-e03a7fd4c0fd",
-    "invariantUuid": "cdb90b57-ed78-4d44-a5b4-7f43a02ec632",
-    "serviceType": "pnf",
-    "serviceRole": "Testing",
-    "vidNotions": {"instantiationUI": "legacy", "modelCategory": "other", "viewEditUI": "legacy"},
-    "isMultiStepDesign": true
-  };
-}
+    };
+
+    const isDiffCustomizationUuidResponse : boolean = service.isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDiffer(node, serviceModelId);
+    expect(isDiffCustomizationUuidResponse).toEqual(expected);
+  });
+
+});
 
 function getStore() {
   return {
index 1115d1b..9e7a021 100644 (file)
@@ -19,7 +19,6 @@ import {NodeInstance} from "../../../shared/models/nodeInstance";
 
 @Injectable()
 export class SharedTreeService {
-  private _sharedTreeService: SharedTreeService;
   constructor(private _store: NgRedux<AppState>) {
   }
 
@@ -54,6 +53,51 @@ export class SharedTreeService {
       : (nodeInstance.modelInfo.modelCustomizationId || nodeInstance.modelInfo.modelInvariantId);
   };
 
+  modelUniqueNameOrId = (instance): string => {
+    if (_.isNil(instance)) {
+      return null;
+    }
+
+    const innerInstance = _.find(instance) || {};
+
+    return instance.originalName
+      || this.modelUniqueId(instance)
+      || innerInstance.originalName
+      || this.modelUniqueId(innerInstance);
+  };
+
+  /**
+   * Finds a model inside a full service model
+   * @param serviceModelFromHierarchy
+   * @param modelTypeName "vnfs" | "networks" | "vfModules" | "collectionResources" | ...
+   * @param modelUniqueNameOrId Either an entry name (i.e. "originalName"), modelCustomizationId or modelInvariantId.
+   *                      Note that modelInvariantId will work only where model lacks a modelCustomizationId.
+   * @param modelName An optional entry name (i.e. "originalName"); will not try to use as id
+   */
+  modelByIdentifiers = (serviceModelFromHierarchy, modelTypeName: string, modelUniqueNameOrId: string, modelName?: string): any => {
+    const logErrorAndReturnUndefined = () =>
+      console.info(`modelByIdentifiers: could not find a model matching query`, {
+        modelTypeName, modelUniqueNameOrId, modelName, serviceModelFromHierarchy
+      });
+
+    if (_.isNil(serviceModelFromHierarchy)) return logErrorAndReturnUndefined();
+
+    const modelsOfType = serviceModelFromHierarchy[modelTypeName];
+    if (_.isNil(modelsOfType)) return logErrorAndReturnUndefined();
+
+    const modelIfModelIdentifierIsEntryName = modelsOfType[modelUniqueNameOrId];
+    const modelIfModeNameExists = _.isNil(modelName) ? null : modelsOfType[modelName];
+
+    if (!_.isNil(modelIfModelIdentifierIsEntryName)) {
+      return modelIfModelIdentifierIsEntryName;
+    } else if (!_.isNil(modelIfModeNameExists)) {
+      return modelIfModeNameExists;
+    } else {
+      // try modelUniqueNameOrId as an id
+      return _.find(modelsOfType, o => (o.customizationUuid || o.invariantUuid) === modelUniqueNameOrId) || logErrorAndReturnUndefined()
+    }
+  };
+
   hasMissingData(instance, dynamicInputs: any, isEcompGeneratedNaming: boolean, requiredFields: string[]): boolean {
     if (!isEcompGeneratedNaming && _.isEmpty(instance.instanceName)) {
       return true;
@@ -120,8 +164,8 @@ export class SharedTreeService {
   /**********************************************
    * should return true if can delete
    **********************************************/
-  shouldShowDelete(node): boolean {
-    return this.shouldShowButtonGeneric(node, "delete")
+  shouldShowDelete(node, serviceModelId): boolean {
+    return this.shouldShowButtonGeneric(node, "delete", serviceModelId)
   }
 
   /**********************************************
@@ -173,21 +217,74 @@ export class SharedTreeService {
    ****************************************************/
   shouldShowUpgrade(node, serviceModelId): boolean {
     if (FeatureFlagsService.getFlagState(Features.FLAG_FLASH_REPLACE_VF_MODULE, this._store) &&
-      this.isThereAnUpdatedLatestVersion(serviceModelId)) {
-      return this.shouldShowButtonGeneric(node, VNFMethods.UPGRADE);
+      (this.isThereAnUpdatedLatestVersion(serviceModelId)) || this.isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDiffer(node, serviceModelId)) {
+      return this.shouldShowButtonGeneric(node, VNFMethods.UPGRADE, serviceModelId);
     }
     else {
       return false
     }
   }
 
-  private isThereAnUpdatedLatestVersion(serviceModelId) : boolean{
-    let serviceInstance = this._store.getState().service.serviceInstance[serviceModelId];
+
+  isVfmoduleAlmostPartOfModelOnlyCustomizationUuidDiffer(vfModuleNode, serviceModelId) : boolean {
+    /*
+    for `true`, should all:
+    1. parent vnf found by model-mane
+    2. vfmodule found by invariant
+    3. vfmodule diff by customization
+     */
+
+    if (_.isNil(vfModuleNode.data)) {
+      return false;
+    }
+
+    const vnfHierarchy = this.getParentVnfHierarchy(vfModuleNode, serviceModelId);
+    if (_.isNil(vnfHierarchy)) {
+      return false;
+    }
+
+    const vfModuleHierarchyByInvariantId =  this.getVfModuleHFromVnfHierarchyByInvariantId(vfModuleNode, vnfHierarchy);
+    if(_.isNil(vfModuleHierarchyByInvariantId)){
+      return false;
+    }
+
+    return vfModuleHierarchyByInvariantId.customizationUuid
+      && (vfModuleHierarchyByInvariantId.customizationUuid !== vfModuleNode.data.modelCustomizationId);
+  }
+
+  getParentVnfHierarchy(vfModuleNode, serviceModelId) {
+    if (vfModuleNode.parent && vfModuleNode.parent.data) {
+      return this._store.getState().service.serviceHierarchy[serviceModelId].vnfs[vfModuleNode.parent.data.modelName];
+    } else {
+      return null;
+    }
+  }
+
+  getVfModuleHFromVnfHierarchyByInvariantId(vfModuleNode, parentVnfHierarchy) {
+    if(vfModuleNode.data.modelInvariantId && parentVnfHierarchy && parentVnfHierarchy.vfModules){
+      return _.find(parentVnfHierarchy.vfModules, o => o.invariantUuid === vfModuleNode.data.modelInvariantId);
+    }
+    return null;
+  }
+
+
+  isThereAnUpdatedLatestVersion(serviceModelId) : boolean{
+    let serviceInstance = this.getServiceInstance(serviceModelId);
     return !_.isNil(serviceInstance.latestAvailableVersion) && (Number(serviceInstance.modelInfo.modelVersion) < serviceInstance.latestAvailableVersion);
   }
 
-  private shouldShowButtonGeneric(node, method) {
+  private getServiceInstance(serviceModelId): any {
+    return this._store.getState().service.serviceInstance[serviceModelId];
+  }
+
+  shouldShowButtonGeneric(node, method, serviceModelId) {
     const mode = this._store.getState().global.drawingBoardStatus;
+    const isMacro = !(this.getServiceInstance(serviceModelId).isALaCarte);
+
+    if (isMacro) { //if macro action allowed only for service level
+      return false;
+    }
+
     if (!_.isNil(node) && !_.isNil(node.data) && !_.isNil(node.data.action) && !_.isNil(node.data.menuActions[method])) {
       if (mode !== DrawingBoardModes.EDIT || node.data.action === ServiceInstanceActions.Create) {
         return false;
@@ -269,7 +366,7 @@ export class SharedTreeService {
    ************************************************/
   getExistingInstancesWithDeleteMode(node, serviceModelId: string, type: string): number {
     let counter = 0;
-    const existingInstances = this._store.getState().service.serviceInstance[serviceModelId][type];
+    const existingInstances = this.getServiceInstance(serviceModelId)[type];
     const modelUniqueId = node.data.modelUniqueId;
     if (!_.isNil(existingInstances)) {
       for (let instanceKey in existingInstances) {
@@ -358,7 +455,13 @@ export class SharedTreeService {
     AuditInfoModalComponent.openInstanceAuditInfoModal.next({
       instanceId: serviceModelId,
       type: instanceType,
-      model: modelInfoService.getModel(node.data.modelName, instance, this._store.getState().service.serviceHierarchy[serviceModelId]),
+      model: modelInfoService.getModel(
+        this.modelByIdentifiers(
+          this._store.getState().service.serviceHierarchy[serviceModelId],
+          modelInfoService.name,
+          this.modelUniqueNameOrId(instance), node.data.modelName
+        )
+      ),
       instance
     });
   }
index cbe8445..59988f7 100644 (file)
@@ -26,8 +26,8 @@ export class ServicePlanningComponent implements OnInit {
   }
 
   pageMode: DrawingBoardModes = DrawingBoardModes.CREATE;
-  @ViewChild(DrawingBoardTreeComponent) drawingModelTree;
-  @ViewChild(AvailableModelsTreeComponent) availableModelTree;
+  @ViewChild(DrawingBoardTreeComponent, {static: false}) drawingModelTree;
+  @ViewChild(AvailableModelsTreeComponent, {static: false}) availableModelTree;
 
   isShowTree(): boolean {
     return true;
index 16b8c01..dcc32a5 100644 (file)
         <td class="mediumTd" id="created"><custom-ellipsis [id]="data.created" [value]="data.created | date:'MMM. dd, yyyy HH:mm'"></custom-ellipsis></td>
         <td class="last" id="jobStatus" [ngClass]="data.jobStatus">
           <custom-popover [value]="data.serviceStatus.tooltip"  [popoverType]="data?.serviceStatus?.color" style="float: left;">
-            <svg-icon
+            <custom-icon
               id="jobStatusIcon-{{i}}"
               (click)="auditInfo(data)"
               [mode]="data.serviceStatus.color"
               [size]="'large'"
               [name]="data.serviceStatus.iconClassName">
-            </svg-icon>
+            </custom-icon>
 
           </custom-popover>
           <div class="menu-div" (click)="onContextMenu($event, data)" [attr.data-tests-id]="'menu-'+data.jobId">
index 4f84b71..f27faac 100644 (file)
@@ -39,7 +39,7 @@ export class InstantiationStatusComponent implements OnInit {
   instantiationStatusComponentService: InstantiationStatusComponentService;
   configurationService : ConfigurationService;
   serviceInfoData: ServiceInfoModel[] = null;
-  @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
+  @ViewChild(ContextMenuComponent, {static: false}) public contextMenu: ContextMenuComponent;
 
   public contextMenuActions: Array<MenuAction> = [
     {
index 5145784..3dff92c 100644 (file)
           </div>
         </div>
         <div class="col-md-8 right-panel">
-          <div class="row" *ngIf="showVidStatus"><span class="table-title">VID status</span></div>
+          <div class="row" *ngIf="showVidStatus">
+            <div class="col-md-6 leftColumn"><span class="table-title">VID status</span></div>
+            <div class="col-md-6 rightColumn"><span *ngIf="showMoreAuditInfoLink">
+                <a id="full_screen_link" target="_parent" title="Full-screen audit info" [href]="readOnlyRetryUrl()">
+                  <i class="fa fa-external-link"></i>
+                </a>
+            </span></div>
+          </div>
           <div class="row" *ngIf="showVidStatus">
             <table id="service-instantiation-audit-info-vid"  class="table table-bordered">
               <thead class="thead-dark">
index 95e9825..3a7f4ec 100644 (file)
@@ -10,6 +10,7 @@ import {IframeService} from "../../utils/iframe.service";
 import {NgRedux} from "@angular-redux/store";
 import {AppState} from "../../store/reducers";
 import {AuditInfoModalComponentService} from "./auditInfoModal.component.service";
+import {FeatureFlagsService, Features} from "../../services/featureFlag/feature-flags.service";
 
 @Component({
   selector: 'audit-info-modal',
@@ -19,11 +20,13 @@ import {AuditInfoModalComponentService} from "./auditInfoModal.component.service
 export class AuditInfoModalComponent {
   static openModal: Subject<ServiceInfoModel> = new Subject<ServiceInfoModel>();
   static openInstanceAuditInfoModal: Subject<{instanceId , type, model, instance}> = new Subject<{instanceId , type, model, instance}>();
-  @ViewChild('auditInfoModal') public auditInfoModal: ModalDirective;
+  @ViewChild('auditInfoModal', {static: false}) public auditInfoModal: ModalDirective;
   title: string = 'Service Instantiation Information';
   modelInfoItems: ModelInformationItem[] = [];
   serviceModel: ServiceModel;
   serviceModelName: string;
+  serviceModelId: string;
+  jobId: string;
   vidInfoData: AuditStatus[] = [];
   msoInfoData: AuditStatus[] = [];
   isAlaCarte: boolean;
@@ -32,15 +35,18 @@ export class AuditInfoModalComponent {
   model: any;
   instanceId: string;
   isALaCarteFlagOn: boolean;
+  showMoreAuditInfoLink: boolean;
   type : string = "Service";
   showVidStatus : boolean = true;
   auditInfoModalComponentService : AuditInfoModalComponentService;
   constructor(private _serviceInfoService: ServiceInfoService, private _iframeService : IframeService,
               private _auditInfoModalComponentService : AuditInfoModalComponentService,
+              private _featureFlagsService: FeatureFlagsService,
               private store: NgRedux<AppState>) {
     this.auditInfoModalComponentService = this._auditInfoModalComponentService;
     AuditInfoModalComponent.openModal.subscribe((jobData: ServiceInfoModel) => {
       this.isALaCarteFlagOn = this.store.getState().global.flags['FLAG_A_LA_CARTE_AUDIT_INFO'];
+      this.showMoreAuditInfoLink = _featureFlagsService.getFlagState(Features.FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO);
       this.initializeProperties();
       this.showVidStatus = true;
       if (jobData) {
@@ -48,6 +54,8 @@ export class AuditInfoModalComponent {
         this.openAuditInfoModal(jobData);
         _iframeService.addClassOpenModal(this.parentElementClassName);
         this.serviceModelName = jobData.serviceModelName ? jobData.serviceModelName : '';
+        this.serviceModelId = jobData.serviceModelId;
+        this.jobId = jobData.jobId;
         this.auditInfoModal.show();
       } else {
         _iframeService.removeClassCloseModal(this.parentElementClassName);
@@ -57,6 +65,7 @@ export class AuditInfoModalComponent {
 
     AuditInfoModalComponent.openInstanceAuditInfoModal.subscribe(({instanceId  , type ,  model, instance}) => {
       this.showVidStatus = false;
+      this.showMoreAuditInfoLink = false;
       this.initializeProperties();
       this.setModalTitles(type);
       this.serviceModelName = AuditInfoModalComponentService.getInstanceModelName(model);
@@ -118,5 +127,8 @@ export class AuditInfoModalComponent {
   onNavigate(){
     window.open("http://ecompguide.web.att.com:8000/#ecomp_ug/c_ecomp_ops_vid.htmll#r_ecomp_ops_vid_bbglossary", "_blank");
   }
+
+  readOnlyRetryUrl = (): string =>
+    `../../serviceModels.htm?more#/servicePlanning/RETRY?serviceModelId=${this.serviceModelId}&jobId=${this.jobId}`
 }
 
diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.html
new file mode 100644 (file)
index 0000000..a50522a
--- /dev/null
@@ -0,0 +1,16 @@
+<div>
+  <button class="custom-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}"
+          [disabled]="disabled || show_spinner"
+          [attr.data-tests-id]="testId">
+    <custom-icon
+      *ngIf="icon_name"
+      [name]="icon_name"
+      [mode]="icon_mode"
+      [size]="'medium'"
+    >
+    </custom-icon>
+    {{text}}
+  </button>
+  <custom-icon *ngIf="show_spinner" name="spinner" [size]="'medium'" class="sdc-button__spinner"
+            [ngClass]="{left: spinner_position === placement.right}"></custom-icon>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.scss
new file mode 100644 (file)
index 0000000..89f90d4
--- /dev/null
@@ -0,0 +1,273 @@
+.custom-button {
+  order: 1;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: row;
+  outline: none;
+  border-radius: 2px;
+  padding: 0 12px;
+  height: 36px;
+  line-height: 36px;
+  width: 120px;
+  min-width: 90px;
+  cursor: pointer;
+  text-align: center;
+  text-transform: uppercase;
+  font-family: OpenSans-Regular, Arial, sans-serif;
+  font-style: normal;
+  font-weight: 400;
+  font-size: 14px;
+  /*** Sizes ***/
+  /*** Sizes ***/
+  /*** Buttons with icons ***/
+}
+
+.custom-button:disabled {
+  cursor: default;
+}
+
+.custom-button.sdc-button__primary {
+  border: 1px solid transparent;
+  background-color: #009fdb;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__primary:not(:disabled):hover, .custom-button.sdc-button__primary:not(:disabled):active {
+  background-color: #1eb9f3;
+}
+
+.custom-button.sdc-button__primary:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #1eb9f3;
+  box-shadow: 0px 0px 0px 1px #1eb9f3;
+}
+
+.custom-button.sdc-button__primary:disabled {
+  background: #9dd9ef;
+}
+
+.custom-button.sdc-button__secondary {
+  border: 1px solid #009fdb;
+  background-color: transparent;
+  color: #009fdb;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):hover, .custom-button.sdc-button__secondary:not(:disabled):active {
+  background-color: #1eb9f3;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active) {
+  color: #1eb9f3;
+  box-shadow: inset 0px 0px 0px 0px #0568ae, 0px 0px 0px 1px #009fdb;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active):hover {
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__secondary:disabled {
+  color: #9dd9ef;
+  border-color: #9dd9ef;
+}
+
+.custom-button.sdc-button__link {
+  background-color: transparent;
+  color: #009fdb;
+  fill: #009fdb;
+  border: none;
+}
+
+.custom-button.sdc-button__link:not(:disabled):hover, .custom-button.sdc-button__link:not(:disabled):active {
+  color: #1eb9f3;
+}
+
+.custom-button.sdc-button__link:not(:disabled):focus:not(:active) {
+  border: 1px solid #0568ae;
+  color: #1eb9f3;
+}
+
+.custom-button.sdc-button__link:disabled {
+  color: #9dd9ef;
+}
+
+.custom-button.sdc-button__success {
+  border: 1px solid transparent;
+  background-color: #4ca90c;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__success:not(:disabled):hover, .custom-button.sdc-button__success:not(:disabled):active {
+  background-color: #57c00e;
+}
+
+.custom-button.sdc-button__success:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #57c00e;
+  box-shadow: 0px 0px 0px 1px #57c00e;
+}
+
+.custom-button.sdc-button__success:disabled {
+  background: #a5d485;
+}
+
+.custom-button.sdc-button__error, .custom-button.sdc-button__alert {
+  border: 1px solid transparent;
+  background-color: #cf2a2a;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__error:not(:disabled):hover, .custom-button.sdc-button__error:not(:disabled):active, .custom-button.sdc-button__alert:not(:disabled):hover, .custom-button.sdc-button__alert:not(:disabled):active {
+  background-color: #ed4141;
+}
+
+.custom-button.sdc-button__error:not(:disabled):focus:not(:active), .custom-button.sdc-button__alert:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #ed4141;
+  box-shadow: 0px 0px 0px 1px #ed4141;
+}
+
+.custom-button.sdc-button__error:disabled, .custom-button.sdc-button__alert:disabled {
+  background: #f4adad;
+}
+
+.custom-button.sdc-button__warning {
+  border: 1px solid transparent;
+  background-color: #ffb81c;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__warning:not(:disabled):hover, .custom-button.sdc-button__warning:not(:disabled):active {
+  background-color: #f6c632;
+}
+
+.custom-button.sdc-button__warning:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #f6c632;
+  box-shadow: 0px 0px 0px 1px #f6c632;
+}
+
+.custom-button.sdc-button__warning:disabled {
+  background: #ffdb8d;
+}
+
+.custom-button.sdc-button__info {
+  border: 1px solid transparent;
+  background-color: #009fdb;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__info:not(:disabled):hover, .custom-button.sdc-button__info:not(:disabled):active {
+  background-color: #1eb9f3;
+}
+
+.custom-button.sdc-button__info:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #1eb9f3;
+  box-shadow: 0px 0px 0px 1px #1eb9f3;
+}
+
+.custom-button.sdc-button__info:disabled {
+  background: #9dd9ef;
+}
+
+.custom-button.sdc-button__file-opener input[type=file] {
+  height: 36px;
+  opacity: 0;
+  position: absolute;
+  cursor: pointer;
+}
+
+.custom-button.btn-xx-large {
+  width: 350px;
+}
+
+.custom-button.btn-xx-large input[type=file] {
+  width: 350px;
+}
+
+.custom-button.btn-x-large {
+  width: 250px;
+}
+
+.custom-button.btn-x-large input[type=file] {
+  width: 250px;
+}
+
+.custom-button.btn-large {
+  width: 180px;
+}
+
+.custom-button.btn-large input[type=file] {
+  width: 180px;
+}
+
+.custom-button.btn-medium {
+  width: 140px;
+}
+
+.custom-button.btn-medium input[type=file] {
+  width: 140px;
+}
+
+.custom-button.btn-small {
+  width: 110px;
+}
+
+.custom-button.btn-small input[type=file] {
+  width: 110px;
+}
+
+.custom-button.btn-x-small {
+  width: 90px;
+}
+
+.custom-button.btn-x-small input[type=file] {
+  width: 90px;
+}
+
+.custom-button.btn-default {
+  width: auto;
+}
+
+.custom-button.btn-default input[type=file] {
+  width: auto;
+}
+
+.custom-button.sdc-icon-right {
+  flex-direction: row-reverse;
+}
+
+.custom-button.sdc-icon-right .svg-icon {
+  margin-left: 15px;
+}
+
+.custom-button.sdc-icon-left {
+  flex-direction: row;
+}
+
+.custom-button.sdc-icon-left .svg-icon {
+  margin-right: 15px;
+}
+
+.custom-button svg {
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.sdc-button__wrapper {
+  display: inline-flex;
+}
+
+.sdc-button__spinner {
+  padding-top: 6px;
+  margin: 0 2px;
+}
+
+.sdc-button__spinner.left {
+  order: 2;
+}
diff --git a/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts b/vid-webpack-master/src/app/shared/components/customButton/custom-button.component.ts
new file mode 100644 (file)
index 0000000..61fa028
--- /dev/null
@@ -0,0 +1,65 @@
+import {Component, HostBinding, Input, OnInit} from "@angular/core";
+import {IButtonComponent} from "../customModal/models/modal-button.model";
+import {ButtonType} from "../customModal/models/button.type";
+import {Mode} from "./models/mode.model";
+import {Placement} from "../customModal/models/modal.placement";
+
+
+@Component({
+  selector: "sdc-button",
+  templateUrl: './custom-button.component.html',
+  styleUrls: ['./custom-button.component.scss']
+
+})
+
+export class CustomButtonComponent implements OnInit, IButtonComponent {
+  @Input() public text: string;
+  @Input() public disabled: boolean;
+  @Input() public type: ButtonType;
+  @Input() public icon_mode: Mode;
+  @Input() public size: string;
+  @Input() public preventDoubleClick: boolean;
+  @Input() public icon_name: string;
+  @Input() public icon_position: string;
+  @Input() public show_spinner: boolean;
+  @Input() public spinner_position: Placement;
+  @Input() public testId: string;
+
+  public placement = Placement;
+  private lastClick: Date;
+  public iconPositionClass: string;
+
+  @HostBinding('class.sdc-button__wrapper') true;
+
+  constructor() {
+    this.type = ButtonType.primary;
+    this.size = "default";
+    this.disabled = false;
+  }
+
+  public ngOnInit(): void {
+    this.iconPositionClass = this.icon_position ? 'sdc-icon-' + this.icon_position : '';
+  }
+
+  public onClick = (e): void => {
+    const now: Date = new Date();
+    if (this.preventDoubleClick && this.lastClick && (now.getTime() - this.lastClick.getTime()) <= 500) {
+      e.preventDefault();
+      e.stopPropagation();
+    }
+    this.lastClick = now;
+  }
+
+  public disableButton = () => {
+    if (!this.disabled) {
+      this.disabled = true;
+    }
+  }
+
+  public enableButton = () => {
+    if (this.disabled) {
+      this.disabled = false;
+    }
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts b/vid-webpack-master/src/app/shared/components/customButton/models/mode.model.ts
new file mode 100644 (file)
index 0000000..c8a7dde
--- /dev/null
@@ -0,0 +1,10 @@
+export enum Mode {
+  primary = 'primary',
+  primary2 = 'primary2',
+  secondary = 'secondary',
+  success = 'success',
+  error = 'error',
+  warning = 'warning',
+  info = 'info',
+  white = 'white'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.html
new file mode 100644 (file)
index 0000000..0ac56d2
--- /dev/null
@@ -0,0 +1,2 @@
+<div [ngClass]="classes" [attr.disabled]="disabled || undefined" [innerHtml]="svgIconContentSafeHtml"
+     [attr.data-tests-id]="testId"></div>
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.scss
new file mode 100644 (file)
index 0000000..54b3757
--- /dev/null
@@ -0,0 +1,297 @@
+@import 'node_modules/onap-ui-common/lib/scss/variables.scss';
+
+:host {
+  display: inline-flex;
+}
+
+@mixin color-icon($primary-color) {
+  color: $primary-color;
+  fill: $primary-color;
+}
+
+@mixin color-icon-hover($secondary-color) {
+  &.clickable {
+    cursor: pointer;
+    &:not([disabled]):hover, &:active, &:focus {
+      @include color-icon($secondary-color);
+    }
+  }
+}
+
+@mixin color-icon-label($primary-color) {
+  @include color-icon($primary-color);
+
+  .custom-icon {
+    @include color-icon($primary-color);
+  }
+}
+
+@mixin color-icon-label-hover($secondary-color) {
+  &.clickable {
+    &:not([disabled]):hover, &:active, &:focus {
+      @include color-icon-label($secondary-color);
+    }
+  }
+}
+
+/deep/ .custom-icon {
+  display: inline-flex;
+  width: 24px;
+  height: 24px;
+  box-sizing: content-box;
+
+  & > svg {
+    width: 100%;
+    height: 100%;
+  }
+
+  &[disabled] {
+    opacity: 0.7;
+  }
+
+  &.mode-primary {
+    @include color-icon($blue);
+    @include color-icon-hover($light-blue);
+  }
+
+  &.mode-primary2 {
+    @include color-icon($dark-gray);
+    @include color-icon-hover($light-blue);
+  }
+
+  &.mode-secondary {
+    @include color-icon($gray);
+    @include color-icon-hover($dark-gray);
+  }
+
+  &.mode-success {
+    @include color-icon($green);
+  }
+
+  &.mode-error {
+    @include color-icon($red);
+  }
+
+  &.mode-warning {
+    @include color-icon($yellow);
+  }
+
+  &.mode-info {
+    @include color-icon($text-black);
+    @include color-icon-hover($dark-blue);
+  }
+
+  &.mode-white {
+    @include color-icon($white);
+    @include color-icon-hover($light-gray);
+  }
+
+  &.size-x_small {
+    width: 8px;
+    height: 8px;
+  }
+
+  &.size-small {
+    width: 12px;
+    height: 12px;
+  }
+
+  &.size-medium {
+    width: 16px;
+    height: 16px;
+  }
+
+  &.size-large {
+    width: 24px;
+    height: 24px;
+  }
+
+  &.size-x_large {
+    width: 36px;
+    height: 36px;
+  }
+
+  &.size-x_x_large {
+    width: 48px;
+    height: 48px;
+  }
+
+  &.bg-type-circle {
+    border-radius: 50%;
+    padding: 6px;
+  }
+
+  &.bg-type-rectangle {
+    padding: 6px;
+  }
+
+  &.bg-color-purple {
+    background-color: $purple;
+  }
+
+  &.bg-color-light-blue {
+    background-color: $light-blue;
+  }
+
+  &.bg-color-green {
+    background-color: $green;
+  }
+
+  &.bg-color-red {
+    background-color: $red;
+  }
+
+  &.bg-color-yellow {
+    background-color: $yellow;
+  }
+
+  &.bg-color-blue {
+    background-color: $blue;
+  }
+
+  &.bg-color-lightBlue {
+    background-color: $light-blue;
+  }
+
+  &.bg-color-darkBlue {
+    background-color: $dark-blue;
+  }
+
+  &.bg-color-darkBlue2 {
+    background-color: $dark-blue2;
+  }
+
+  &.bg-color-disabledBlue {
+    background-color: $disabled-blue;
+  }
+
+  &.bg-color-gray {
+    background-color: $gray;
+  }
+
+  &.bg-color-white {
+    background-color: $white;
+  }
+
+  &.bg-color-transparent {
+    background-color:transparent;
+  }
+  &.bg-color-silver {
+    background-color: $light-silver;
+  }
+}
+
+.custom-icon-wrapper {
+  display: inline-flex;
+  justify-content: center;
+  align-items: center;
+
+  &.custom-icon-label {
+  }
+
+  &.custom-icon {
+  }
+
+  &[disabled] {
+    opacity: 0.7;
+  }
+
+  &.label-placement-bottom {
+    flex-direction: column;
+    .custom-icon-label {
+      margin-top: 0.25em;
+    }
+  }
+
+  &.label-placement-right {
+    .custom-icon-label {
+      margin-left: 0.25em;
+    }
+  }
+
+  &.label-placement-top {
+    flex-direction: column-reverse;
+    .custom-icon-label {
+      margin-bottom: 0.25em;
+    }
+  }
+
+  &.label-placement-left {
+    flex-direction: row-reverse;
+    .custom-icon-label {
+      margin-right: 0.25em;
+    }
+  }
+
+  &.mode-primary {
+    @include color-icon-label($blue);
+    @include color-icon-label-hover($light-blue);
+  }
+
+  &.mode-secondary {
+    @include color-icon-label($gray);
+    @include color-icon-label-hover($light-blue);
+  }
+
+  &.mode-success {
+    @include color-icon-label($green);
+  }
+
+  &.mode-error {
+    @include color-icon-label($red);
+  }
+
+  &.mode-warning {
+    @include color-icon-label($yellow);
+  }
+
+  &.mode-info {
+    @include color-icon-label($text-black);
+    @include color-icon-label-hover($light-blue);
+  }
+
+  &.size-x_small {
+    font-size: 8px;
+    line-height: 10px;
+
+    .custom-icon {
+      @extend .custom-icon.size-x_small;
+    }
+  }
+
+  &.size-small {
+    font-size: 12px;
+    line-height: 14px;
+
+    .custom-icon {
+      @extend .custom-icon.size-small;
+    }
+  }
+
+  &.size-medium {
+    font-size: 16px;
+    line-height: 20px;
+
+    .custom-icon {
+      @extend .custom-icon.size-medium;
+    }
+  }
+
+  &.size-large {
+    font-size: 24px;
+    line-height: 28px;
+
+    .custom-icon {
+      @extend .custom-icon.size-large;
+    }
+  }
+
+  &.size-x_large {
+    font-size: 34px;
+    line-height: 40px;
+
+    .custom-icon {
+      @extend .custom-icon.size-x_large;
+    }
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts b/vid-webpack-master/src/app/shared/components/customIcon/custom-icon.component.ts
new file mode 100644 (file)
index 0000000..c59bc59
--- /dev/null
@@ -0,0 +1,85 @@
+import {Component, Input, OnChanges, SimpleChanges} from "@angular/core";
+import {Mode} from "../customButton/models/mode.model";
+import {Size} from "./models/icon-size.model";
+import {BackgroundShape} from "./models/background-shape.model";
+import {BackgroundColor} from "./models/background-color.model";
+import {DomSanitizer, SafeHtml} from "@angular/platform-browser";
+import {iconsMap} from 'onap-ui-common';
+
+@Component({
+  selector: 'custom-icon',
+  templateUrl: './custom-icon.component.html',
+  styleUrls: ['./custom-icon.component.scss'],
+})
+export class SvgIconComponent implements OnChanges {
+
+  @Input() public name: string;
+  @Input() public type: string;
+  @Input() public mode: Mode;
+  @Input() public size: Size;
+  @Input() public backgroundShape: BackgroundShape;
+  @Input() public backgroundColor: BackgroundColor;
+  @Input() public disabled: boolean;
+  @Input() public clickable: boolean;
+  @Input() public className: any;
+  @Input() public testId: string;
+
+  public svgIconContent: string;
+  public svgIconContentSafeHtml: SafeHtml;
+  public svgIconCustomClassName: string;
+  public classes: string;
+
+  constructor(protected domSanitizer: DomSanitizer) {
+    this.size = Size.medium;
+    this.disabled = false;
+    this.type = this.type || "common";
+  }
+
+  static Icons(): { [key: string]: string } {
+    return iconsMap;
+  }
+
+  public ngOnChanges(changes: SimpleChanges) {
+    this.updateSvgIconByName();
+    this.buildClasses();
+  }
+
+  protected updateSvgIconByName() {
+    this.svgIconContent = iconsMap[this.type][this.name] || null;
+    if (this.svgIconContent) {
+      this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.svgIconContent);
+      this.svgIconCustomClassName = '__' + this.name.replace(/\s+/g, '_');
+    } else {
+      this.svgIconContentSafeHtml = null;
+      this.svgIconCustomClassName = 'missing';
+    }
+  }
+
+  private buildClasses = (): void => {
+    const _classes = ['svg-icon'];
+    if (this.mode) {
+      _classes.push('mode-' + this.mode);
+    }
+    if (this.size) {
+      _classes.push('size-' + this.size);
+    }
+    if (this.clickable) {
+      !this.disabled && _classes.push('clickable');
+    }
+    if (this.svgIconCustomClassName) {
+      _classes.push(this.svgIconCustomClassName);
+    }
+    if (this.className) {
+      _classes.push(this.className);
+    }
+    if (this.backgroundShape) {
+      _classes.push('bg-type-' + this.backgroundShape);
+    }
+    if (this.backgroundShape && this.backgroundColor) {
+      _classes.push('bg-color-' + this.backgroundColor);
+    } else if (this.backgroundShape && !this.backgroundColor) {
+      _classes.push('bg-color-primary');
+    }
+    this.classes = _classes.join(" ");
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/background-color.model.ts
new file mode 100644 (file)
index 0000000..324f51b
--- /dev/null
@@ -0,0 +1,15 @@
+export enum BackgroundColor {
+  gray = 'gray',
+  purple = 'purple',
+  blue = 'blue',
+  lightBlue = 'light-blue',
+  darkBlue = 'dark-blue',
+  darkBlue2 = 'dark-blue2',
+  disabledBlue = 'disabled-blue',
+  white = 'white',
+  transparent = 'transparent',
+  green = 'green',
+  red = 'red',
+  yellow = 'yellow',
+  silver ='silver'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/background-shape.model.ts
new file mode 100644 (file)
index 0000000..924ce3d
--- /dev/null
@@ -0,0 +1,4 @@
+export enum BackgroundShape {
+  circle = 'circle',
+  rectangle = 'rectangle'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts b/vid-webpack-master/src/app/shared/components/customIcon/models/icon-size.model.ts
new file mode 100644 (file)
index 0000000..a6cd9f5
--- /dev/null
@@ -0,0 +1,7 @@
+export enum Size {
+  x_large = 'x_large',
+  large = 'large',
+  medium = 'medium',
+  small = 'small',
+  x_small = 'x_small'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.html
new file mode 100644 (file)
index 0000000..999d5d3
--- /dev/null
@@ -0,0 +1,15 @@
+<div>
+  <div class="custom-loader-wrapper" *ngIf="!global" [attr.data-tests-id]="testId">
+    <div class="custom-loader-background" *ngIf="active"
+         [style.top]="offset.top" [style.left]="offset.left" [style.width]="offset.width"
+         [style.height]="offset.height">
+      <div class="custom-loader {{ size }}" *ngIf="active"></div>
+    </div>
+    <ng-content></ng-content>
+  </div>
+  <div *ngIf="global && active" [attr.data-tests-id]="testId">
+    <div class="custom-loader-global-wrapper custom-loader-background">
+      <div class="custom-loader {{ size }}"></div>
+    </div>
+  </div>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.scss
new file mode 100644 (file)
index 0000000..7572c6e
--- /dev/null
@@ -0,0 +1,222 @@
+.custom-loader-background {
+  background-color: #000000;
+  position: absolute;
+  z-index: 9999;
+  opacity: 0.5;
+  display: flex;
+  justify-content: center;
+  align-items: center; }
+
+.sdc-loader-wrapper-absolute {
+  position: absolute;
+  top: 0; }
+
+.custom-loader {
+  z-index: 10002; }
+
+.custom-loader-global-wrapper {
+  position: fixed;
+  width: 100%;
+  height: 100%; }
+
+.loader-fixed {
+  display: block;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%; }
+@keyframes fadein {
+  from {
+    opacity: 0; }
+  to {
+    opacity: 0.8; } }
+
+/* Firefox < 16 */
+@-moz-keyframes fadein {
+  from {
+    opacity: 0; }
+  to {
+    opacity: 0.8; } }
+
+/* Safari, Chrome and Opera > 12.1 */
+@-webkit-keyframes fadein {
+  from {
+    opacity: 0; }
+  to {
+    opacity: 0.8; } }
+
+/* Internet Explorer */
+@-ms-keyframes fadein {
+  from {
+    opacity: 0; }
+  to {
+    opacity: 0.8; } }
+
+/* Opera < 12.1 */
+@-o-keyframes fadein {
+  from {
+    opacity: 0; }
+  to {
+    opacity: 0.8; } }
+
+@keyframes fadeout {
+  from {
+    opacity: 0.8; }
+  to {
+    opacity: 0; } }
+
+/* Firefox < 16 */
+@-moz-keyframes fadeout {
+  from {
+    opacity: 0.8; }
+  to {
+    opacity: 0; } }
+
+/* Safari, Chrome and Opera > 12.1 */
+@-webkit-keyframes fadeout {
+  from {
+    opacity: 0.8; }
+  to {
+    opacity: 0; } }
+
+/* Internet Explorer */
+@-ms-keyframes fadeout {
+  from {
+    opacity: 0.8; }
+  to {
+    opacity: 0; } }
+
+/* Opera < 12.1 */
+@-o-keyframes fadeout {
+  from {
+    opacity: 0.8; }
+  to {
+    opacity: 0; } }
+
+.custom-loader {
+  height: 63px;
+  width: 63px;
+  position: absolute; }
+
+.custom-loader.small {
+  transform: scale(0.26); }
+
+.custom-loader.medium {
+  transform: scale(0.5); }
+
+.custom-loader.large {
+  transform: scale(1); }
+
+.custom-loader::before {
+  background-color: #eaeaea;
+  border-radius: 50%;
+  box-shadow: 21px 21px 0px 0px #eaeaea, 0px 42px 0px 0px #eaeaea, -21px 21px 0px 0px #eaeaea;
+  content: '';
+  display: block;
+  height: 21px;
+  width: 21px;
+  position: absolute;
+  left: 50%;
+  margin-left: -10.5px; }
+
+.custom-loader::after {
+  border-radius: 50%;
+  content: '';
+  display: block;
+  position: absolute;
+  height: 21px;
+  width: 21px;
+  animation: dot-move-2 4.5s infinite ease-in; }
+
+@keyframes dot-move {
+  0% {
+    background-color: #1eb9f3;
+    left: 21px;
+    top: 0; }
+  25% {
+    background-color: #ffb81c;
+    left: 42px;
+    top: 21px; }
+  50% {
+    background-color: #caa2dd;
+    left: 21px;
+    top: 42px; }
+  75% {
+    background-color: #f6c632;
+    left: 0;
+    top: 21px; }
+  100% {
+    background-color: #1eb9f3;
+    left: 21px;
+    top: 0; } }
+
+@keyframes dot-move-2 {
+  0% {
+    background-color: #1eb9f3;
+    left: 21px;
+    top: 0; }
+  6.25% {
+    background-color: #1eb9f3;
+    left: 42px;
+    top: 21px; }
+  12.5% {
+    background-color: #1eb9f3;
+    left: 21px;
+    top: 42px; }
+  18.75% {
+    background-color: #1eb9f3;
+    left: 0;
+    top: 21px; }
+  25% {
+    background-color: #ffb81c;
+    left: 21px;
+    top: 0; }
+  31.25% {
+    background-color: #ffb81c;
+    left: 42px;
+    top: 21px; }
+  37.5% {
+    background-color: #ffb81c;
+    left: 21px;
+    top: 42px; }
+  43.75% {
+    background-color: #ffb81c;
+    left: 0;
+    top: 21px; }
+  50% {
+    background-color: #caa2dd;
+    left: 21px;
+    top: 0; }
+  56.25% {
+    background-color: #caa2dd;
+    left: 42px;
+    top: 21px; }
+  62.5% {
+    background-color: #caa2dd;
+    left: 21px;
+    top: 42px; }
+  68.75% {
+    background-color: #caa2dd;
+    left: 0;
+    top: 21px; }
+  75% {
+    background-color: #f6c632;
+    left: 21px;
+    top: 0; }
+  81.25% {
+    background-color: #f6c632;
+    left: 42px;
+    top: 21px; }
+  87.5% {
+    background-color: #f6c632;
+    left: 21px;
+    top: 42px; }
+  93.75% {
+    background-color: #f6c632;
+    left: 0;
+    top: 21px; }
+  100% {
+    background-color: #1eb9f3;
+    left: 21px;
+    top: 0; } }
diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.component.ts
new file mode 100644 (file)
index 0000000..98bcce1
--- /dev/null
@@ -0,0 +1,76 @@
+import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewContainerRef} from "@angular/core";
+import {LoaderSize} from "./models/loader-size.model";
+import {LoaderService} from "./custom-loader.service";
+
+@Component({
+  selector: "custom-loader",
+  templateUrl: './custom-loader.component.html',
+  styleUrls: ['./custom-loader.component.scss']
+
+})
+
+export class LoaderComponent implements OnInit, OnDestroy {
+  @Input() active: number;
+  @Input() size?: LoaderSize;
+  @Input() global?: boolean;
+  @Input() name?: string;
+  @Input() testId: string;
+  @Input() relative: boolean;
+  @Output() activeChange: EventEmitter<number> = new EventEmitter<number>();
+  private offset : {
+    top: string;
+    left: string;
+    width: string;
+    height: string;
+  };
+
+  constructor(private loaderService: LoaderService, private viewContainerRef: ViewContainerRef) {
+    this.active = 0;
+    this.size = LoaderSize.large;
+    this.global = false;
+  }
+
+  public ngOnInit(): void {
+    if (this.name !== undefined) {
+      this.loaderService.register(this.name, this);
+    }
+    this.setLoaderPlace();
+  }
+
+  public ngOnDestroy(): void {
+    if (this.name !== undefined) {
+      this.loaderService.unregister(this.name);
+    }
+  }
+
+  public activate() {
+    this.active++;
+    this.activeChange.emit(this.active);
+  }
+
+  public deactivate() {
+    if (this.active > 0) {
+      this.active--;
+      this.activeChange.emit(this.active);
+    }
+  }
+  public setLoaderPlace = () => {
+    if (this.relative === true) {
+      let parentElement = this.viewContainerRef.element.nativeElement.parentElement;
+      this.offset = {
+        left: (parentElement.offsetLeft !== undefined) ? parentElement.offsetLeft + "px" : undefined,
+        top: (parentElement.offsetTop !== undefined) ? parentElement.offsetTop + "px" : undefined,
+        width: (parentElement.offsetWidth !== undefined) ? parentElement.offsetWidth + "px" : undefined,
+        height: (parentElement.offsetHeight !== undefined) ? parentElement.offsetHeight + "px" : undefined
+      };
+    } else {
+      this.offset = {
+        left: '0px',
+        top: '0px',
+        width: '100%',
+        height: '100%'
+      }
+    }
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts b/vid-webpack-master/src/app/shared/components/customLoader/custom-loader.service.ts
new file mode 100644 (file)
index 0000000..398eac2
--- /dev/null
@@ -0,0 +1,34 @@
+import {Injectable} from "@angular/core";
+import {LoaderComponent} from "./custom-loader.component";
+
+@Injectable()
+export class LoaderService {
+
+  private mainLoaderName = 'general';
+  public registeredLoaders = {};
+
+  register(name: string, loader: LoaderComponent) {
+    if (!this.registeredLoaders[name]) {
+      this.registeredLoaders[name] = loader;
+    }
+  }
+
+  unregister(name: string) {
+    if (this.registeredLoaders[name]) {
+      delete this.registeredLoaders[name];
+    }
+  }
+
+  activate(name: string = this.mainLoaderName) {
+    if (this.registeredLoaders[name]) {
+      this.registeredLoaders[name].activate();
+    }
+  }
+
+  deactivate(name: string = this.mainLoaderName) {
+    if (this.registeredLoaders[name]) {
+      this.registeredLoaders[name].deactivate();
+    }
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts b/vid-webpack-master/src/app/shared/components/customLoader/models/loader-size.model.ts
new file mode 100644 (file)
index 0000000..d5400ef
--- /dev/null
@@ -0,0 +1,5 @@
+export enum LoaderSize {
+  large = 'large',
+  medium = 'medium',
+  small = 'small',
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.html
new file mode 100644 (file)
index 0000000..a50522a
--- /dev/null
@@ -0,0 +1,16 @@
+<div>
+  <button class="custom-button sdc-button__{{ type }} btn-{{ size }} {{ iconPositionClass }}"
+          [disabled]="disabled || show_spinner"
+          [attr.data-tests-id]="testId">
+    <custom-icon
+      *ngIf="icon_name"
+      [name]="icon_name"
+      [mode]="icon_mode"
+      [size]="'medium'"
+    >
+    </custom-icon>
+    {{text}}
+  </button>
+  <custom-icon *ngIf="show_spinner" name="spinner" [size]="'medium'" class="sdc-button__spinner"
+            [ngClass]="{left: spinner_position === placement.right}"></custom-icon>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.scss
new file mode 100644 (file)
index 0000000..89f90d4
--- /dev/null
@@ -0,0 +1,273 @@
+.custom-button {
+  order: 1;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: row;
+  outline: none;
+  border-radius: 2px;
+  padding: 0 12px;
+  height: 36px;
+  line-height: 36px;
+  width: 120px;
+  min-width: 90px;
+  cursor: pointer;
+  text-align: center;
+  text-transform: uppercase;
+  font-family: OpenSans-Regular, Arial, sans-serif;
+  font-style: normal;
+  font-weight: 400;
+  font-size: 14px;
+  /*** Sizes ***/
+  /*** Sizes ***/
+  /*** Buttons with icons ***/
+}
+
+.custom-button:disabled {
+  cursor: default;
+}
+
+.custom-button.sdc-button__primary {
+  border: 1px solid transparent;
+  background-color: #009fdb;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__primary:not(:disabled):hover, .custom-button.sdc-button__primary:not(:disabled):active {
+  background-color: #1eb9f3;
+}
+
+.custom-button.sdc-button__primary:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #1eb9f3;
+  box-shadow: 0px 0px 0px 1px #1eb9f3;
+}
+
+.custom-button.sdc-button__primary:disabled {
+  background: #9dd9ef;
+}
+
+.custom-button.sdc-button__secondary {
+  border: 1px solid #009fdb;
+  background-color: transparent;
+  color: #009fdb;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):hover, .custom-button.sdc-button__secondary:not(:disabled):active {
+  background-color: #1eb9f3;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active) {
+  color: #1eb9f3;
+  box-shadow: inset 0px 0px 0px 0px #0568ae, 0px 0px 0px 1px #009fdb;
+}
+
+.custom-button.sdc-button__secondary:not(:disabled):focus:not(:active):hover {
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__secondary:disabled {
+  color: #9dd9ef;
+  border-color: #9dd9ef;
+}
+
+.custom-button.sdc-button__link {
+  background-color: transparent;
+  color: #009fdb;
+  fill: #009fdb;
+  border: none;
+}
+
+.custom-button.sdc-button__link:not(:disabled):hover, .custom-button.sdc-button__link:not(:disabled):active {
+  color: #1eb9f3;
+}
+
+.custom-button.sdc-button__link:not(:disabled):focus:not(:active) {
+  border: 1px solid #0568ae;
+  color: #1eb9f3;
+}
+
+.custom-button.sdc-button__link:disabled {
+  color: #9dd9ef;
+}
+
+.custom-button.sdc-button__success {
+  border: 1px solid transparent;
+  background-color: #4ca90c;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__success:not(:disabled):hover, .custom-button.sdc-button__success:not(:disabled):active {
+  background-color: #57c00e;
+}
+
+.custom-button.sdc-button__success:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #57c00e;
+  box-shadow: 0px 0px 0px 1px #57c00e;
+}
+
+.custom-button.sdc-button__success:disabled {
+  background: #a5d485;
+}
+
+.custom-button.sdc-button__error, .custom-button.sdc-button__alert {
+  border: 1px solid transparent;
+  background-color: #cf2a2a;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__error:not(:disabled):hover, .custom-button.sdc-button__error:not(:disabled):active, .custom-button.sdc-button__alert:not(:disabled):hover, .custom-button.sdc-button__alert:not(:disabled):active {
+  background-color: #ed4141;
+}
+
+.custom-button.sdc-button__error:not(:disabled):focus:not(:active), .custom-button.sdc-button__alert:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #ed4141;
+  box-shadow: 0px 0px 0px 1px #ed4141;
+}
+
+.custom-button.sdc-button__error:disabled, .custom-button.sdc-button__alert:disabled {
+  background: #f4adad;
+}
+
+.custom-button.sdc-button__warning {
+  border: 1px solid transparent;
+  background-color: #ffb81c;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__warning:not(:disabled):hover, .custom-button.sdc-button__warning:not(:disabled):active {
+  background-color: #f6c632;
+}
+
+.custom-button.sdc-button__warning:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #f6c632;
+  box-shadow: 0px 0px 0px 1px #f6c632;
+}
+
+.custom-button.sdc-button__warning:disabled {
+  background: #ffdb8d;
+}
+
+.custom-button.sdc-button__info {
+  border: 1px solid transparent;
+  background-color: #009fdb;
+  color: #ffffff;
+}
+
+.custom-button.sdc-button__info:not(:disabled):hover, .custom-button.sdc-button__info:not(:disabled):active {
+  background-color: #1eb9f3;
+}
+
+.custom-button.sdc-button__info:not(:disabled):focus:not(:active) {
+  border: 1px solid #ffffff;
+  background-color: #1eb9f3;
+  box-shadow: 0px 0px 0px 1px #1eb9f3;
+}
+
+.custom-button.sdc-button__info:disabled {
+  background: #9dd9ef;
+}
+
+.custom-button.sdc-button__file-opener input[type=file] {
+  height: 36px;
+  opacity: 0;
+  position: absolute;
+  cursor: pointer;
+}
+
+.custom-button.btn-xx-large {
+  width: 350px;
+}
+
+.custom-button.btn-xx-large input[type=file] {
+  width: 350px;
+}
+
+.custom-button.btn-x-large {
+  width: 250px;
+}
+
+.custom-button.btn-x-large input[type=file] {
+  width: 250px;
+}
+
+.custom-button.btn-large {
+  width: 180px;
+}
+
+.custom-button.btn-large input[type=file] {
+  width: 180px;
+}
+
+.custom-button.btn-medium {
+  width: 140px;
+}
+
+.custom-button.btn-medium input[type=file] {
+  width: 140px;
+}
+
+.custom-button.btn-small {
+  width: 110px;
+}
+
+.custom-button.btn-small input[type=file] {
+  width: 110px;
+}
+
+.custom-button.btn-x-small {
+  width: 90px;
+}
+
+.custom-button.btn-x-small input[type=file] {
+  width: 90px;
+}
+
+.custom-button.btn-default {
+  width: auto;
+}
+
+.custom-button.btn-default input[type=file] {
+  width: auto;
+}
+
+.custom-button.sdc-icon-right {
+  flex-direction: row-reverse;
+}
+
+.custom-button.sdc-icon-right .svg-icon {
+  margin-left: 15px;
+}
+
+.custom-button.sdc-icon-left {
+  flex-direction: row;
+}
+
+.custom-button.sdc-icon-left .svg-icon {
+  margin-right: 15px;
+}
+
+.custom-button svg {
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.sdc-button__wrapper {
+  display: inline-flex;
+}
+
+.sdc-button__spinner {
+  padding-top: 6px;
+  margin: 0 2px;
+}
+
+.sdc-button__spinner.left {
+  order: 2;
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts b/vid-webpack-master/src/app/shared/components/customModal/components/modalButton/modal-button.component.ts
new file mode 100644 (file)
index 0000000..d93c678
--- /dev/null
@@ -0,0 +1,28 @@
+import {Component, EventEmitter, HostListener, Input, Output} from "@angular/core";
+import {CustomButtonComponent} from "../../../customButton/custom-button.component";
+
+@Component({
+  selector: "custom-modal-button",
+  templateUrl: './modal-button.component.html',
+  styleUrls: ['./modal-button.component.scss']
+})
+export class CustomModalButtonComponent extends CustomButtonComponent {
+
+  @Input() public id?: string;
+  @Input() public callback: Function;
+  @Input() public closeModal: boolean;
+  @Output() closeModalEvent: EventEmitter<any> = new EventEmitter<any>();
+  @HostListener('click') invokeCallback = (): void => {
+    if (this.callback) {
+      this.callback();
+    }
+    if (this.closeModal) {
+      this.closeModalEvent.emit();
+    }
+  }
+
+  constructor() {
+    super();
+    this.closeModal = false;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts b/vid-webpack-master/src/app/shared/components/customModal/components/modalCloseButton/modal-close-button.component.ts
new file mode 100644 (file)
index 0000000..9528f77
--- /dev/null
@@ -0,0 +1,36 @@
+import {Component, ComponentRef, Input} from "@angular/core";
+import {ModalComponent} from "../../modal.component";
+import {CustomButtonComponent} from "../../../customButton/custom-button.component";
+import {RippleAnimationAction} from "../../directives/ripple-click.animation.directive";
+
+
+@Component({
+  selector: "sdc-modal-close-button",
+  template: `
+    <div class="sdc-modal__close-button"
+         customRippleClickAnimation
+         [ngClass]="disabled ? 'disabled' : ''"
+         [rippleOnAction]="!disabled && rippleAnimationAction"
+         [attr.data-tests-id]="testId"
+         (click)="!disabled && closeModal('close')"
+    >
+      <custom-icon name="close" [mode]="disabled? 'secondary' : 'info'" size="small"></custom-icon>
+    </div>
+  `
+})
+export class ModalCloseButtonComponent extends CustomButtonComponent {
+
+  @Input() testId: string;
+  @Input() disabled: boolean;
+  @Input() modalInstanceRef: ComponentRef<ModalComponent>;
+
+  public rippleAnimationAction: RippleAnimationAction = RippleAnimationAction.MOUSE_ENTER;
+
+  constructor() {
+    super();
+  }
+
+  public closeModal = (btnName: string): void => {
+    this.modalInstanceRef.instance.closeModal(btnName);
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts b/vid-webpack-master/src/app/shared/components/customModal/directives/ripple-click.animation.directive.ts
new file mode 100644 (file)
index 0000000..d343d5d
--- /dev/null
@@ -0,0 +1,47 @@
+import { Directive, Input, HostBinding, HostListener } from "@angular/core";
+
+export enum RippleAnimationAction {
+  CLICK = 0,
+  MOUSE_ENTER = 1
+}
+
+@Directive({
+  selector: `[customRippleClickAnimation]`
+})
+export class CustomRippleClickAnimationDirective {
+  private animated: boolean;
+
+  @Input() rippleClickDisabled: boolean;
+  @Input() rippleOnAction:RippleAnimationAction = RippleAnimationAction.CLICK;
+
+  @HostBinding('class.sdc-ripple-click__animated') animationClass: string;
+
+  @HostListener('click') onClick() {
+    if(this.rippleOnAction === RippleAnimationAction.CLICK){
+      this.animateStart();
+    }
+  }
+
+  @HostListener('mouseenter') onMouseEnter() {
+    //console.log("Mouseenter!", this.rippleOnAction);
+    if(this.rippleOnAction === RippleAnimationAction.MOUSE_ENTER){
+      this.animateStart();
+    }
+  }
+
+  private animateStart():void{
+    if (!this.rippleClickDisabled) {
+      this.animated = true;
+      this.animationClass = 'sdc-ripple-click__animated';
+    }
+  }
+  @HostListener('animationend') onAnimationComplete() {
+    this.animated = false;
+    this.animationClass = '';
+  }
+
+  constructor() {
+    this.rippleClickDisabled = false;
+    this.animated = false;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/modal.component.html b/vid-webpack-master/src/app/shared/components/customModal/modal.component.html
new file mode 100644 (file)
index 0000000..059eb8a
--- /dev/null
@@ -0,0 +1,46 @@
+<div>
+  <div class="modal-background" [@toggleBackground]="modalVisible" ></div>
+  <div class="sdc-modal {{size}}">
+    <div class="sdc-modal__wrapper sdc-modal-type-{{type}}" [@toggleModal]="modalVisible" (@toggleModal.done)="modalToggled($event)">
+
+      <div class="sdc-modal__header sdc-{{type}}__header">
+        <div class="sdc-modal__icon" *ngIf="type!='custom'" [innerHtml]="svgIconContentSafeHtml"></div>
+
+        <div *ngIf="title" class="title" >
+          {{ title }}
+          <custom-icon
+            *ngIf="titleIcon"
+            [name]="titleIcon.iconName"
+            [mode]="titleIcon.iconMode"
+            [size]="titleIcon.iconSize">
+          </custom-icon>
+        </div>
+        <sdc-modal-close-button #modalCloseButton [testId]="'close' | calculateTestId : testId" [modalInstanceRef]="instanceRef"></sdc-modal-close-button>
+      </div>
+
+      <div class="sdc-modal__content">
+        <div *ngIf="message" [innerHtml]="message"></div>
+        <div #dynamicContentContainer></div>
+        <div class="disabled-modal" *ngIf="isDisabled"></div>
+      </div>
+
+      <div class="sdc-modal__footer">
+        <custom-modal-button *ngFor="let button of buttons"
+                          [text]="button.text"
+                          [type]="button.type || 'primary'"
+                          [disabled]="button.disabled"
+                          [size] = "button.size ? button.size : 'default'"
+                          [closeModal]="button.closeModal"
+                          [spinner_position]="button.spinner_position"
+                          [show_spinner]="button.show_spinner"
+                          [callback]="button.callback"
+                          [testId]="'button-' + button.text | calculateTestId : testId"
+                          (closeModalEvent)="closeModal(button.text)"
+        >
+        </custom-modal-button>
+      </div>
+
+    </div>
+  </div>
+</div>
+
diff --git a/vid-webpack-master/src/app/shared/components/customModal/modal.component.ts b/vid-webpack-master/src/app/shared/components/customModal/modal.component.ts
new file mode 100644 (file)
index 0000000..eb001c0
--- /dev/null
@@ -0,0 +1,166 @@
+import {
+  Component,
+  ComponentRef,
+  EventEmitter,
+  Input,
+  OnInit,
+  Output,
+  Renderer,
+  ViewChild,
+  ViewContainerRef
+} from "@angular/core";
+import {animate, style, transition, trigger} from "@angular/animations";
+import {TitleIconDetails} from "./models/modal.model";
+import {ModalType} from "./models/modal.type";
+import {DomSanitizer, SafeHtml} from "@angular/platform-browser";
+import {ModalCloseButtonComponent} from "./components/modalCloseButton/modal-close-button.component";
+import {CustomModalButtonComponent} from "./components/modalButton/modal-button.component";
+
+@Component({
+  selector: 'sdc-modal',
+  templateUrl: './modal.component.html',
+  animations: [
+    trigger('toggleBackground', [
+      transition('* => 1', [style({ opacity: 0 }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]),
+      transition('1 => *', [animate('.35s cubic-bezier(0.23, 1, 0.32, 1)', style({ opacity: 0 }))])
+    ]),
+    trigger('toggleModal', [
+      transition('* => 1', [style({ opacity: 0, transform: 'translateY(-80px)' }), animate('.45s cubic-bezier(0.23, 1, 0.32, 1)')]),
+      transition('1 => *', [style({ opacity: 1, transform: 'translateY(0px)' }), animate('.35s ease-in-out', style({ opacity: 0, transform: 'translateY(-80px)' }))])
+    ])
+  ]
+})
+
+export class ModalComponent implements OnInit {
+
+  @Input() size: string; 'xl|l|md|sm|xsm';
+  @Input() title: string;
+  @Input() titleIcon: TitleIconDetails;
+  @Input() message: string;
+  @Input() buttons: CustomModalButtonComponent[];
+  @Input() type: ModalType;
+  @Input() testId: string;
+  @Input() isDisabled: boolean;
+  @Input() instanceRef: ComponentRef<ModalComponent>; // the component ref is injected to the component in order to destroy the componet from itself
+
+  @Output() onClose : EventEmitter<string> =  new EventEmitter<string>();
+
+  @ViewChild('modalCloseButton', {static: false})
+  set refCloseButton(_modalCloseButton: ModalCloseButtonComponent) {
+    this.modalCloseButton = _modalCloseButton;
+  }
+
+  modalVisible: boolean;
+  // Allows for custom component as body instead of simple message.
+  @ViewChild('dynamicContentContainer', { read: ViewContainerRef, static: true }) dynamicContentContainer: ViewContainerRef;
+  innerModalContent: ComponentRef<any>;
+
+  public calculatedTestId: string;
+  public modalCloseButton: ModalCloseButtonComponent;
+  public svgIconContentSafeHtml: SafeHtml;
+
+
+  private infoSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24">
+    <defs><path fill="#000" id="info-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.101 4.9,22 11,22 C17.1,22 22,17.101 22,11 C22,4.9 17.1,0 11,0 M11,10 C10.4,
+    10 10,10.4 10,11 L10,15 C10,15.601 10.4,16 11,16 C11.6,16 12,15.601 12,15 L12,11 C12,10.4 11.6,10 11,10 M10.2998,6.2998 C10.0998,6.4998 9.9998,6.6998 9.9998,6.9998 C9.9998,7.2998 10.0998,7.4998 10.2998,7.6998 C10.4998,
+    7.9008 10.6998,7.9998 10.9998,7.9998 C11.2998,7.9998 11.4998,7.9008 11.6998,7.6998 C11.9008,7.4998 11.9998,7.2998 11.9998,6.9998 C11.9998,6.6998 11.9008,6.4998 11.6998,6.2998 C11.2998,5.9008 10.6998,5.9008 10.2998,6.2998"/>
+    </defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#info-a"/></g></svg>`;
+  private warningSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="alert-a" d="M20.5815,18.7997 C20.3815,
+    18.9997 20.0815,19.0997 19.8815,19.0997 L2.8815,19.0997 C2.6815,19.0997 2.5815,19.0997 2.3815,18.9997 C1.8815,18.6997 1.7815,18.0997 1.9815,17.5997 L10.4815,3.4997 C10.5815,3.4007 10.6815,3.1997 10.7815,3.1997 C11.2815,
+    2.9007 11.8815,3.0997 12.1815,3.4997 L20.6825,17.5997 C20.7815,17.6997 20.7815,17.9007 20.7815,18.0997 C20.8815,18.4007 20.6825,18.5997 20.5815,18.7997 M22.3815,16.5997 L13.9815,2.4007 C13.5815,1.6997 12.8815,1.1997 12.0815,
+    0.9997 C11.2815,0.7997 10.4815,0.9007 9.7815,1.2997 C9.3815,1.4997 8.9815,1.9007 8.7815,2.2997 L0.3815,16.5997 C-0.4185,17.9997 0.0815,19.9007 1.4815,20.6997 C1.8815,20.9997 2.3815,21.0997 2.8815,21.0997 L19.8815,
+    21.0997 C20.6825,21.0997 21.4815,20.7997 21.9815,20.1997 C22.5815,19.5997 22.8815,18.9007 22.8815,18.0997 C22.7815,17.5997 22.6825,16.9997 22.3815,16.5997 M11,7 C10.4,7 10,7.4 10,8 L10,12 C10,12.601 10.4,13 11,13 C11.6,13 12,
+    12.601 12,12 L12,8 C12,7.4 11.6,7 11,7 M10.3,15.3 C10.1,15.499 10,15.699 10,15.999 C10,16.3 10.1,16.499 10.3,16.699 C10.5,16.9 10.7,16.999 11,16.999 C11.3,16.999 11.5,16.9 11.7,16.699 C11.9,16.499 12,16.199 12,15.999 C12,
+    15.8 11.9,15.499 11.7,15.3 C11.3,14.9 10.7,14.9 10.3,15.3"/></defs><g fill="#ffb81c" fill-rule="evenodd" transform="translate(1 1)"><use class="sdc-modal__svg-use" xlink:href="#alert-a"/></g></svg>`;
+  private errorSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24"><defs><path fill="#000" id="x-a" d="M11,20 C6,20 2,16 2,11 C2,6 6,2 11,
+    2 C16,2 20,6 20,11 C20,16 16,20 11,20 M11,0 C4.9,0 0,4.9 0,11 C0,17.1 4.9,22 11,22 C17.1,22 22,17.1 22,11 C22,4.9 17.1,0 11,0 M14.2591,7.29935 C13.8591,6.90035 13.2591,6.90035 12.8591,7.29935 L10.5591,9.59935 L8.2591,
+    7.29935 C7.8591,6.90035 7.2591,6.90035 6.8591,7.29935 C6.4591,7.69935 6.4591,8.29935 6.8591,8.69935 L9.1581,10.99935 L6.8591,13.29935 C6.4591,13.69935 6.4591,14.29935 6.8591,14.69935 C7.0591,14.90035 7.2591,14.99935 7.5591,
+    14.99935 C7.8591,14.99935 8.0591,14.90035 8.2591,14.69935 L10.5591,12.40035 L12.8591,14.69935 C13.0591,14.90035 13.3591,14.99935 13.5591,14.99935 C13.7591,14.99935 14.0591,14.90035 14.2591,14.69935 C14.6581,14.29935 14.6581,
+    13.69935 14.2591,13.29935 L11.9591,10.99935 L14.2591,8.69935 C14.6581,8.29935 14.6581,7.69935 14.2591,7.29935"/></defs><g fill="none" fill-rule="evenodd" transform="translate(1 1)">
+    <use class="sdc-modal__svg-use" xlink:href="#x-a"/></g></svg>`;
+  private successSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30" viewBox="0 0 24 24" fill="#4ca90c"><path id="success+20-a" d="M20.1825992,10.445793 C20.6735306,
+    10.445793 21.0008182,10.7730806 21.0008182,11.264012 L21.0008182,12.0004091 C21.0008182,16.9915451 16.9915451,21 12.0004091,21 C7.00927315,21 3,16.9915451 3,12.0004091 C3,7.00927315 7.00927315,3 12.0004091,3 C13.3095595,3 14.536888,
+    3.3272876 15.6823947,3.81821901 C16.0915042,3.98186281 16.255148,4.47279422 16.0915042,4.88190372 C15.9278604,5.29101323 15.436929,5.45465703 15.0278194,5.29101323 C14.0459566,4.88190372 13.0640938,4.63643802 12.0004091,
+    4.63643802 C7.90931406,4.63643802 4.63643802,7.90931406 4.63643802,12.0004091 C4.63643802,16.0906859 7.90931406,19.363562 12.0004091,19.363562 C16.0915042,19.363562 19.3643802,16.0906859 19.3643802,12.0004091 L19.3643802,
+    11.264012 C19.3643802,10.7730806 19.6916678,10.445793 20.1825992,10.445793 Z M21.5737352,4.06343925 C21.9002046,4.39072685 21.9002046,4.88165826 21.5737352,5.20894586 L12.5733261,14.209355 C12.4096823,14.3729988 12.1642166,
+    14.4548207 12.0005728,14.4548207 C11.836929,14.4548207 11.5914632,14.3729988 11.4278194,14.209355 L8.97316242,11.7546979 C8.64587481,11.4274103 8.64587481,10.9364789 8.97316242,10.6091913 C9.30045002,10.2819037 9.79138143,
+    10.2819037 10.118669,10.6091913 L12.0005728,12.491095 L20.4282286,4.06343925 C20.7555162,3.73615164 21.2464476,3.73615164 21.5737352,4.06343925 Z"></path></svg>`;
+  private noSvg = ``;
+
+  constructor(private renderer: Renderer,
+              private domSanitizer: DomSanitizer) {
+    this.modalVisible = true;
+  }
+
+  ngOnInit() {
+
+    switch (this.type) {
+      case ModalType.info:
+        this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.infoSvg);
+        break;
+      case ModalType.warning:
+        this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.warningSvg);
+        break;
+      case ModalType.error:
+        this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.errorSvg);
+        break;
+      case ModalType.success:
+        this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.successSvg);
+        break;
+      default:
+        this.svgIconContentSafeHtml = this.domSanitizer.bypassSecurityTrustHtml(this.noSvg);
+    }
+  }
+
+  public modalToggled = (toggleEvent: any) => {
+    if (!toggleEvent.toState) {
+      this.instanceRef.destroy();
+    }
+  }
+
+  public getCloseButton = (): ModalCloseButtonComponent => {
+    return this.modalCloseButton;
+  }
+
+  public getButtonById = (id: string): CustomModalButtonComponent => {
+    // Support ES5
+    // return this.buttons.find((button) => {
+    return this.buttons.filter((button) => {
+      return button.id && button.id === id;
+    })[0];
+  }
+
+  public getButtons = (): CustomModalButtonComponent[] => {
+    return this.buttons;
+  }
+
+  public setButtons = (_buttons: CustomModalButtonComponent[]): void => {
+    this.buttons = _buttons;
+  }
+
+  public getTitle = (): string => {
+    return this.title;
+  }
+
+  public setTitle = (_title: string): void => {
+    this.title = _title;
+  }
+
+  public hoverAnimation(evn: MouseEvent) {
+    this.renderer.setElementClass(evn.target as HTMLElement, 'sdc-ripple-click__animated', true);
+    // evn.taregt.classList.add('sdc-ripple-click__animated');
+  }
+
+  public closeModal = (btnName : string): void => {
+    this.onClose.emit(btnName);
+    this.modalVisible = false;
+  }
+
+  public disabledModal = (isDisabled: boolean): void => {
+    this.isDisabled = isDisabled;
+    this.buttons.forEach((button: CustomModalButtonComponent) => {
+      button.disabled = isDisabled;
+    });
+    this.modalCloseButton.disabled = false;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts b/vid-webpack-master/src/app/shared/components/customModal/models/button.type.ts
new file mode 100644 (file)
index 0000000..a067301
--- /dev/null
@@ -0,0 +1,8 @@
+export enum ButtonType {
+  primary = 'primary',
+  secondary = 'secondary',
+  success = 'success',
+  error = 'error',
+  warning = 'warning',
+  info = 'info'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal-button.model.ts
new file mode 100644 (file)
index 0000000..5e1f4a4
--- /dev/null
@@ -0,0 +1,15 @@
+import {ButtonType} from "onap-ui-angular/dist/dist/common";
+import {Placement} from "./modal.placement";
+
+export interface IButtonComponent {
+  text: string;
+  disabled?: boolean;
+  type?: ButtonType;
+  testId?: string;
+  preventDoubleClick?: boolean;
+  icon_name?: string;
+  icon_position?: string;
+  show_spinner?: boolean;
+  spinner_position?: Placement;
+  size?: string;
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.model.ts
new file mode 100644 (file)
index 0000000..4b814f0
--- /dev/null
@@ -0,0 +1,26 @@
+import {ModalType} from "./modal.type";
+import {IButtonComponent} from "./modal-button.model";
+
+export interface IModalConfig {
+  size?: string; // xl|l|md|sm|xsm
+  title?: string;
+  titleIcon?: TitleIconDetails;
+  message?: string;
+  buttons?: IModalButtonComponent[];
+  testId?: string;
+  type?: ModalType;
+}
+
+export interface IModalButtonComponent extends IButtonComponent {
+  id?: string;
+  callback?: () => void;
+  closeModal?: boolean;
+}
+
+export interface TitleIconDetails {
+  iconName?: string;
+  iconMode?: string;
+  iconSize?: string;
+}
+
+
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.placement.ts
new file mode 100644 (file)
index 0000000..f7f229c
--- /dev/null
@@ -0,0 +1,6 @@
+export enum Placement {
+  left = 'left',
+  right = 'right',
+  top = 'top',
+  bottom = 'bottom'
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.size.ts
new file mode 100644 (file)
index 0000000..0a96810
--- /dev/null
@@ -0,0 +1,7 @@
+export enum ModalSize {
+  xlarge = "xl",
+  large = "l",
+  medium = "md",
+  small = "sm",
+  xsmall = "xsm"
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts b/vid-webpack-master/src/app/shared/components/customModal/models/modal.type.ts
new file mode 100644 (file)
index 0000000..ca987eb
--- /dev/null
@@ -0,0 +1,10 @@
+export enum ModalType {
+  info = 'info',
+  warning = 'warning',
+  error = 'error',
+  success = 'success',
+  action = 'action',
+  custom = 'custom'
+}
+
+
diff --git a/vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts b/vid-webpack-master/src/app/shared/components/customModal/services/create-dynamic-component.service.ts
new file mode 100644 (file)
index 0000000..64fe66c
--- /dev/null
@@ -0,0 +1,107 @@
+import {
+  ApplicationRef,
+  ComponentFactoryResolver,
+  ComponentRef,
+  EmbeddedViewRef,
+  Injectable,
+  Injector, Type, ViewContainerRef
+} from "@angular/core";
+
+@Injectable()
+export class CreateDynamicComponentService {
+
+  constructor(private componentFactoryResolver: ComponentFactoryResolver,
+              private applicationRef: ApplicationRef,
+              private injector: Injector) {
+  }
+
+  /**
+   * Gets the root view container to inject the component to.
+   *
+   * @returns {ComponentRef<any>}
+   *
+   * @memberOf InjectionService
+   */
+  private getRootViewContainer(): ComponentRef<any> {
+    const rootComponents = this.applicationRef['components'];
+    if (rootComponents.length) {
+      return rootComponents[0];
+    }
+    throw new Error('View Container not found! ngUpgrade needs to manually set this via setRootViewContainer.');
+  }
+
+  /**
+   * Gets the html element for a component ref.
+   *
+   * @param {ComponentRef<any>} componentRef
+   * @returns {HTMLElement}
+   *
+   * @memberOf InjectionService
+   */
+  private getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {
+    return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
+  }
+
+  /**
+   * Gets the root component container html element.
+   *
+   * @returns {HTMLElement}
+   *
+   * @memberOf InjectionService
+   */
+  private getRootViewContainerNode(): HTMLElement {
+    return this.getComponentRootNode(this.getRootViewContainer());
+  }
+
+  /**
+   * Projects the inputs onto the component
+   *
+   * @param {ComponentRef<any>} component
+   * @param {*} options
+   * @returns {ComponentRef<any>}
+   *
+   * @memberOf InjectionService
+   */
+  private projectComponentInputs(component: ComponentRef<any>, options: any): ComponentRef<any> {
+    if (options) {
+      const props = Object.getOwnPropertyNames(options);
+      for (const prop of props) {
+        component.instance[prop] = options[prop];
+      }
+    }
+
+    return component;
+  }
+
+  public createComponentDynamically<T>(componentClass: Type<T>, options: any = {}, location: Element = this.getRootViewContainerNode()): ComponentRef<any> {
+    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentClass);
+    const componentRef = componentFactory.create(this.injector);
+    const componentRootNode = this.getComponentRootNode(componentRef);
+
+    // project the options passed to the component instance
+    this.projectComponentInputs(componentRef, options);
+    this.applicationRef.attachView(componentRef.hostView);
+
+    componentRef.onDestroy(() => {
+      this.applicationRef.detachView(componentRef.hostView);
+    });
+
+    location.appendChild(componentRootNode);
+    return componentRef;
+  }
+
+  /**
+   * Inserts a component into an existing viewContainer
+   * @param componentType - type of component to create
+   * @param options - Inputs to project on new component
+   * @param vcRef - viewContainerRef in which to insert the newly created component
+   */
+  public insertComponentDynamically<T>(componentType: Type<T>, options: any = {}, vcRef: ViewContainerRef): ComponentRef<any> {
+    const factory = this.componentFactoryResolver.resolveComponentFactory(componentType);
+    const dynamicComponent = factory.create(vcRef.parentInjector);
+    this.projectComponentInputs(dynamicComponent, options);
+    vcRef.insert(dynamicComponent.hostView);
+    return dynamicComponent;
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts b/vid-webpack-master/src/app/shared/components/customModal/services/modal.service.ts
new file mode 100644 (file)
index 0000000..f46ee48
--- /dev/null
@@ -0,0 +1,64 @@
+import {ComponentRef, Injectable, Type} from "@angular/core";
+import {CreateDynamicComponentService} from "./create-dynamic-component.service";
+import {ModalType} from "../models/modal.type";
+import {ButtonType} from "../models/button.type";
+import {ModalButtonComponent} from "onap-ui-angular/dist/modals/modal-button.component";
+import {ModalSize} from "../models/modal.size";
+import {IModalConfig} from "../models/modal.model";
+import {ModalComponent} from "../modal.component";
+
+
+@Injectable()
+export class ModalService {
+
+  constructor(private createDynamicComponentService: CreateDynamicComponentService) {
+  }
+
+  private getBaseModal = (type: ModalType | ButtonType, title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => {
+    const modalConfig = {
+      size: ModalSize.small,
+      title: title,
+      message: message,
+      testId: testId,
+      buttons: buttons ? buttons : [{text: 'OK', type: type, closeModal: true}],
+      type: type
+    } as IModalConfig;
+    const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig);
+    return modalInstance.instance;
+  };
+
+  /* Shortcut method to open basic modals with title, message, and OK button that simply closes the modal. */
+  public openInfoModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => {
+
+    return this.getBaseModal(ModalType.info, title, message, testId, buttons);
+  };
+
+  public openWarningModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => {
+    return this.getBaseModal(ModalType.warning, title, message, testId, buttons);
+  };
+
+  public openErrorModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => {
+    return this.getBaseModal(ModalType.error, title, message, testId, buttons);
+  };
+
+  public openSuccessModal = (title: string, message: string, testId: string, buttons?: ModalButtonComponent[]): ModalComponent => {
+    return this.getBaseModal(ModalType.success, title, message, testId, buttons);
+  };
+
+  public openCustomModal = (modalConfig: IModalConfig, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => {
+    const modalInstance: ComponentRef<ModalComponent> = this.openModal(modalConfig);
+    this.createInnnerComponent(modalInstance, dynamicComponentType, dynamicComponentInput);
+    return modalInstance.instance;
+  };
+
+  public createInnnerComponent = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput?: any): void => {
+    modalInstance.instance.innerModalContent = this.createDynamicComponentService.insertComponentDynamically(dynamicComponentType, dynamicComponentInput, modalInstance.instance.dynamicContentContainer);
+  };
+
+  public openModal = (customModalData: IModalConfig): ComponentRef<ModalComponent> => {
+    let modalInstance: ComponentRef<ModalComponent> = this.createDynamicComponentService.createComponentDynamically(ModalComponent, customModalData);
+    modalInstance.instance.instanceRef = modalInstance;
+    return modalInstance;
+  }
+
+}
diff --git a/vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts b/vid-webpack-master/src/app/shared/components/customTooltip/custom-tooltip.component.ts
new file mode 100644 (file)
index 0000000..a8163a6
--- /dev/null
@@ -0,0 +1,20 @@
+import {AfterViewInit, Component, ViewChild, ViewContainerRef} from "@angular/core";
+import {BehaviorSubject} from "rxjs";
+
+@Component({
+  selector: 'tooltip-template',
+  template: `
+    <div class="custom-tooltip-template-container">
+        <ng-container #templateContainer></ng-container>
+    </div>`
+})
+
+export class TooltipTemplateComponent implements AfterViewInit {
+  @ViewChild('templateContainer', {read: ViewContainerRef, static: true}) public container: ViewContainerRef;
+
+  public viewReady: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
+
+  ngAfterViewInit() : void {
+    this.viewReady.next(true);
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts b/vid-webpack-master/src/app/shared/components/customTooltip/tooltip.directive.ts
new file mode 100644 (file)
index 0000000..4c3b8bd
--- /dev/null
@@ -0,0 +1,461 @@
+import {Directive, ElementRef, HostListener, Input, OnInit, Renderer, TemplateRef} from "@angular/core";
+import {CreateDynamicComponentService} from "../customModal/services/create-dynamic-component.service";
+import {TooltipTemplateComponent} from "./custom-tooltip.component";
+
+const pixel = 'px';
+const leftStyle = 'left';
+const topStyle = 'top';
+const showSuffix = 'show';
+const rightBottomSuffix = 'right__bottom';
+const centerMiddleSuffix = 'center__middle';
+
+@Directive({
+  selector: '[custom-tooltip]'
+})
+export class TooltipDirective implements OnInit {
+  @Input('tooltip-text') public text;
+  @Input('tooltip-placement') public placement: TooltipPlacement = TooltipPlacement.Top;
+  @Input('tooltip-css-class') public customCssClass: string;
+  @Input('tooltip-template') public template: TemplateRef<any>;
+  @Input('tooltip-arrow-offset') public arrowOffset: number = 10;
+  @Input('tooltip-arrow-placement') public arrowPlacement: ArrowPlacement = ArrowPlacement.LeftTop;
+  @Input('tooltip-offset') public tooltipOffset: number = 3;
+
+  private cssClass: string = 'sdc-tooltip'; // default css class
+  private tooltip: any; // tooltip html element
+  private elemPosition: any;
+  private tooltipTemplateContainer: any;
+
+  private scrollEventHandler = () => {};
+
+  constructor(
+    private elementRef: ElementRef,
+    private service: CreateDynamicComponentService,
+    private renderer: Renderer) {
+
+    this.elementRef.nativeElement.title = "";
+  }
+
+  @HostListener('mouseenter')
+  public onMouseEnter() {
+    this.show();
+    this.activateScrollEvent();
+  }
+
+  @HostListener('mouseleave')
+  public onMouseLeave() {
+    this.hide();
+    this.deactivateScrollEvent();
+  }
+
+  ngOnInit(): void {
+    this.initScrollEvent();
+  }
+
+  private get ScreenWidth() {
+    return document.documentElement.clientWidth;
+  }
+
+  private get ScreenHeight() {
+    return document.documentElement.clientHeight;
+  }
+
+  private create() {
+    this.tooltipTemplateContainer = this.service.createComponentDynamically(TooltipTemplateComponent, document.body);
+
+    /**
+     * Creating a view (injecting our template) from template in our component.
+     */
+    this.tooltip = this.tooltipTemplateContainer.location.nativeElement.querySelector(
+      '.sdc-tooltip-template-container');
+
+    if (this.template) {
+      this.tooltipTemplateContainer.instance.container.createEmbeddedView(this.template);
+    } else if(this.text) {
+      this.tooltip.textContent = this.text;
+    } else {
+      this.tooltip = undefined;
+    }
+
+    this.setCssClass(true);
+  }
+
+  private destroy() {
+    this.tooltipTemplateContainer.destroy();
+    this.tooltip = null;
+  }
+
+  private show() {
+    this.create();
+
+    /**
+     *  View is ready (AfterViewInit event in template component)
+     */
+    this.tooltipTemplateContainer.instance.viewReady.subscribe((isReady) => {
+      if (isReady) {
+        this.setPosition();
+        this.toggleShowCssClass(true); // add css class
+      }
+    });
+  }
+
+  private hide() {
+    this.toggleShowCssClass(false); // remove css class
+
+    this.destroy();
+  }
+
+  private toggleShowCssClass(isAdd: boolean) {
+    if (this.tooltip) {
+      this.setCssClass(isAdd, '-' + showSuffix);
+    }
+  }
+
+  /**
+   * Adds placement css class and sets tooltip position in style
+   */
+  private setPosition() {
+    const tooltipPos: IPlacementData = this.getPlacementData();
+
+    const placementSuffix: string = TooltipPlacement[tooltipPos.placement].toLowerCase();
+
+    this.setCssClass(true, '-' + placementSuffix);
+
+    this.setAdditionalCssClass(placementSuffix);
+
+    this.renderer.setElementStyle(this.tooltip, topStyle, tooltipPos.top + pixel);
+    this.renderer.setElementStyle(this.tooltip, leftStyle, tooltipPos.left + pixel);
+  }
+
+  private setAdditionalCssClass(placementSuffix: string) {
+    if (this.arrowPlacement === ArrowPlacement.RightBottom) {
+      this.setCssClass(true, '-' + placementSuffix + '-' + rightBottomSuffix);
+    } else if (this.arrowPlacement === ArrowPlacement.CenterMiddle) {
+      this.setCssClass(true, '-' + placementSuffix + '-' + centerMiddleSuffix);
+    }
+  }
+
+  private setCssClass(isAdd: boolean, suffix: string = '') {
+    this.renderer.setElementClass(this.tooltip, this.cssClass + suffix, isAdd);
+
+    if (this.customCssClass) {
+      this.renderer.setElementClass(this.tooltip, this.customCssClass + suffix, isAdd);
+    }
+  }
+
+  /**
+   * Checks the specified placement (first element in array), if it is not valid - checks other placements
+   * @returns {IPlacementData}
+   */
+  private getPlacementData(): IPlacementData {
+    const placement: TooltipPlacement = this.placement;
+    let tooltipPos: IPlacementData;
+
+    const tooltipPosWithPlacement = this.getPlacement.bind(this, placement);
+
+    // TODO add comments - done
+    switch (placement) {
+      case TooltipPlacement.Left:
+        tooltipPos = tooltipPosWithPlacement(
+          TooltipPlacement.Right,
+          TooltipPlacement.Top,
+          TooltipPlacement.Bottom);
+        break;
+
+      case TooltipPlacement.Right:
+        tooltipPos = tooltipPosWithPlacement(
+          TooltipPlacement.Left,
+          TooltipPlacement.Top,
+          TooltipPlacement.Bottom);
+        break;
+
+      case TooltipPlacement.Top:
+        tooltipPos = tooltipPosWithPlacement(
+          TooltipPlacement.Bottom,
+          TooltipPlacement.Left,
+          TooltipPlacement.Right);
+        break;
+
+      case TooltipPlacement.Bottom:
+        tooltipPos = tooltipPosWithPlacement(
+          TooltipPlacement.Top,
+          TooltipPlacement.Left,
+          TooltipPlacement.Right);
+        break;
+    }
+
+    return tooltipPos;
+  }
+
+  /**
+   * Returns valid tooltip position data
+   * @param {TooltipPlacement} placement
+   * @param {TooltipPlacement} additionalPlacements
+   * @returns {IPlacementData}
+   */
+  private getPlacement(placement: TooltipPlacement,
+                       ...additionalPlacements: TooltipPlacement[]
+  ): IPlacementData {
+    const placements: TooltipPlacement[] = [placement, ...additionalPlacements];
+    const filterPlacements = placements
+      .map((pl) => this.getPosition(pl))
+      .filter((item) => this.validatePosition(item));
+    return filterPlacements.length > 0 ? filterPlacements[0] : this.getPosition(placement);
+  }
+
+  /**
+   * Returns input data for getPosition method
+   * @returns {ITooltipPositionParams}
+   */
+  private getPlacementInputParams(): ITooltipPositionParams {
+    this.elemPosition = this.elementRef.nativeElement.getBoundingClientRect();
+
+    return {
+      elemHeight: this.elementRef.nativeElement.offsetHeight,
+      elemLeft: this.elemPosition.left,
+      elemTop: this.elemPosition.top,
+      elemWidth: this.elementRef.nativeElement.offsetWidth,
+      pageYOffset: window.pageYOffset,
+      tooltipHeight: this.tooltip.offsetHeight, // .clientHeight,
+      tooltipOffset: this.tooltipOffset,
+      tooltipWidth: this.tooltip.offsetWidth,
+      arrowOffset: this.arrowOffset
+    };
+  }
+
+  /**
+   * Returns tooltip position data
+   * @param {TooltipPlacement} placement (left, top, right, bottom)
+   * @returns {IPlacementData}
+   */
+  private getPosition(placement: TooltipPlacement): IPlacementData {
+    switch(this.arrowPlacement) {
+      case ArrowPlacement.LeftTop:
+        return this.getLeftTopPosition(placement);
+
+      case ArrowPlacement.RightBottom:
+        return this.getRightBottomPosition(placement);
+    }
+
+    return this.getCenterMiddlePosition(placement);
+  }
+
+  /**
+   * Returns tooltip position data (center / middle arrow)
+   * @param {TooltipPlacement} placement (left, top, right, bottom)
+   * @returns {IPlacementData}
+   */
+  private getCenterMiddlePosition(placement: TooltipPlacement): IPlacementData {
+    let left = 0;
+    let top = 0;
+
+    const inputPos: ITooltipPositionParams = this.getPlacementInputParams();
+    switch (placement) {
+      case TooltipPlacement.Left:
+        left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight / 2;
+        break;
+
+      case TooltipPlacement.Right:
+        left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight / 2;
+        break;
+
+      case TooltipPlacement.Top:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth / 2;
+        top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset;
+        break;
+
+      case TooltipPlacement.Bottom:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth / 2;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset;
+        break;
+    }
+
+    return {
+      height: inputPos.tooltipHeight,
+      left,
+      placement,
+      top,
+      width: inputPos.tooltipWidth,
+      pageYOffset: inputPos.pageYOffset
+    } as IPlacementData;
+  }
+
+  /**
+   * Returns tooltip position data (left / top arrow)
+   * @param {TooltipPlacement} placement (left, top, right, bottom)
+   * @returns {IPlacementData}
+   */
+  private getLeftTopPosition(placement: TooltipPlacement): IPlacementData {
+    let left = 0;
+    let top = 0;
+
+    const inputPos: ITooltipPositionParams = this.getPlacementInputParams();
+    switch (placement) {
+      case TooltipPlacement.Left:
+        left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.arrowOffset;
+        break;
+
+      case TooltipPlacement.Right:
+        left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.arrowOffset;
+        break;
+
+      case TooltipPlacement.Top:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.arrowOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset;
+        break;
+
+      case TooltipPlacement.Bottom:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.arrowOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset;
+        break;
+    }
+
+    return {
+      height: inputPos.tooltipHeight,
+      left,
+      placement,
+      top,
+      width: inputPos.tooltipWidth,
+      pageYOffset: inputPos.pageYOffset
+    } as IPlacementData;
+  }
+
+  /**
+   * Returns tooltip position data (right / bottom arrow)
+   * @param {TooltipPlacement} placement (left, top, right, bottom)
+   * @returns {IPlacementData}
+   */
+  private getRightBottomPosition(placement: TooltipPlacement): IPlacementData {
+    let left = 0;
+    let top = 0;
+
+    const inputPos: ITooltipPositionParams = this.getPlacementInputParams();
+    switch (placement) {
+      case TooltipPlacement.Left:
+        left = inputPos.elemLeft - inputPos.tooltipWidth - inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight + inputPos.arrowOffset;
+        break;
+
+      case TooltipPlacement.Right:
+        left = inputPos.elemLeft + inputPos.elemWidth + inputPos.tooltipOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight / 2 - inputPos.tooltipHeight + inputPos.arrowOffset;
+        break;
+
+      case TooltipPlacement.Top:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth + inputPos.arrowOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset - inputPos.tooltipHeight - inputPos.tooltipOffset;
+        break;
+
+      case TooltipPlacement.Bottom:
+        left = inputPos.elemLeft + inputPos.elemWidth / 2 - inputPos.tooltipWidth + inputPos.arrowOffset;
+        top = inputPos.elemTop + inputPos.pageYOffset + inputPos.elemHeight + inputPos.tooltipOffset;
+        break;
+    }
+
+    return {
+      height: inputPos.tooltipHeight,
+      left,
+      placement,
+      top,
+      width: inputPos.tooltipWidth,
+      pageYOffset: inputPos.pageYOffset
+    } as IPlacementData;
+  }
+
+  /**
+   * Checks if tooltip position is valid
+   * @param {IPlacementData} pos
+   * @returns {boolean}
+   */
+  private validatePosition(pos: IPlacementData): boolean {
+    if (pos.left < 0 || pos.left + pos.width - 1 > this.ScreenWidth) {
+      return false;
+    }
+
+    if (pos.top - pos.pageYOffset < 0 || pos.top - pos.pageYOffset + pos.height - 1 > this.ScreenHeight) {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Scrolling
+   */
+
+  private debounce(func: Function, wait: number, immediate?: boolean) {
+    let timeout;
+    return function() {
+      const context = this;
+      const args = arguments;
+      const later = () => {
+        timeout = null;
+        if (!immediate) {
+          func.apply(context, args);
+        }
+      };
+      const callNow = immediate && !timeout;
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+      if (callNow) {
+        func.apply(context, args);
+      }
+    };
+  }
+
+  private initScrollEvent() {
+    this.scrollEventHandler = this.debounce(() => {
+      try {
+        this.setPosition();
+      } catch (e) {
+
+      }
+    }, 10);
+  }
+
+  private activateScrollEvent() {
+    window.addEventListener('scroll', this.scrollEventHandler , true);
+  }
+
+  private deactivateScrollEvent() {
+    window.removeEventListener('scroll', this.scrollEventHandler , true);
+  }
+}
+
+export enum TooltipPlacement {
+  Left,
+  Right,
+  Top,
+  Bottom
+}
+
+export enum ArrowPlacement {
+  CenterMiddle,
+  LeftTop,
+  RightBottom
+}
+
+interface ITooltipPositionParams {
+  elemLeft: number;
+  elemTop: number;
+  elemWidth: number;
+  elemHeight: number;
+  tooltipWidth: number;
+  tooltipHeight: number;
+  tooltipOffset: number;
+  pageYOffset: number;
+  arrowOffset: number;
+}
+
+interface IPlacementData {
+  left: number;
+  top: number;
+  width: number;
+  height: number;
+  pageYOffset: number;
+  placement?: TooltipPlacement;
+}
index a7b8ac7..9828645 100644 (file)
@@ -6,7 +6,7 @@ import * as _ from 'lodash';
   selector: 'custom-ellipsis',
   template: `
     <span
-      sdc-tooltip
+      custom-tooltip
       class="ellipsis"
       [attr.data-tests-id]="dataTestId"
       id="{{id}}"
index 26362eb..fe7744e 100644 (file)
@@ -8,4 +8,9 @@
          data-toggle="toggle">
   <label class="checkbox-label"
          for="{{data?.dataTestId}}">{{data?.displayName}}</label>
+  <div *ngFor="let extraContent of data?.extraContents" class="form-conrtols">
+    <div [ngSwitch]="extraContent.type">
+      <upload-files *ngSwitchCase="'UPLOAD_FILE'" [uploadFilesModel]="extraContent" [form]="form"></upload-files>
+    </div>
+  </div>
 </div>
index 2c21720..aadf13e 100644 (file)
@@ -11,7 +11,7 @@ import {FileFormControl} from "../../../../models/formControlModels/fileFormCont
 export class FileFormControlComponent {
   @Input() data: FileFormControl = null;
   @Input() form: FormGroup;
-  @ViewChild('fileUploader')
+  @ViewChild('fileUploader', {static: false})
   fileUploader:ElementRef ;
 
   onDelete(event, data, form) {
index 1e8c281..7a7ab72 100644 (file)
@@ -9,7 +9,7 @@ import {FormGroup} from "@angular/forms";
 })
 
 export class InputFormControlComponent{
-  @ViewChild('customInput') element:ElementRef;
+  @ViewChild('customInput', {static: false}) element:ElementRef;
   @Input() data: InputFormControl = null;
   @Input() form: FormGroup;
 
index e82ea5d..83f7227 100644 (file)
@@ -133,13 +133,14 @@ export class SharedControllersService {
     })
   };
 
-  getSDNCControl = (instance: any): FormControlModel => {
+  getSDNCControl = (instance: any, extraContents? : object[]): FormControlModel => {
     return new CheckboxFormControl({
       controlName: SDN_C_PRE_LOAD,
       displayName: 'SDN-C pre-load',
       dataTestId: 'sdncPreLoad',
       value: instance ? instance.sdncPreLoad : false,
-      validations: [new ValidatorModel(ValidatorOptions.required, 'is required')]
+      validations: [new ValidatorModel(ValidatorOptions.required, 'is required')],
+      extraContents
     })
   };
 
@@ -167,7 +168,7 @@ export class SharedControllersService {
       placeHolder: (!isEcompGeneratedNaming) ? 'Instance name' : 'Automatically generated when not provided',
       validations: validations,
       isVisible : true,
-      value : (!isEcompGeneratedNaming || (!_.isNil(instance) && !_.isNil(instance.instanceName)))
+      value : (!isEcompGeneratedNaming || (!_.isNil(instance) && !_.isNil(instance.instanceName) && instance.instanceName !== ""))
         ? this._basicControlGenerator.getDefaultInstanceName(instance, model) : null,
       onKeypress : (event) => {
         const pattern:RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX;
index f3d32b9..154c60f 100644 (file)
@@ -6,12 +6,20 @@ import {AaiService} from "../../../../services/aaiService/aai.service";
 import {GenericFormService} from "../../generic-form.service";
 import {FormBuilder} from "@angular/forms";
 import {LogService} from "../../../../utils/log/log.service";
-import {FormControlModel, ValidatorModel, ValidatorOptions} from "../../../../models/formControlModels/formControl.model";
+import {
+  FormControlModel,
+  ValidatorModel,
+  ValidatorOptions
+} from "../../../../models/formControlModels/formControl.model";
 import {FormControlNames, VfModuleControlGenerator} from "./vfModule.control.generator";
-import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
+import {FeatureFlagsService, Features} from "../../../../services/featureFlag/feature-flags.service";
 import {VfModuleInstance} from "../../../../models/vfModuleInstance";
 import {VfModule} from "../../../../models/vfModule";
 import {SharedControllersService} from "../sharedControlles/shared.controllers.service";
+import {AppState} from "../../../../store/reducers";
+import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
+import {instance, mock, when} from "ts-mockito";
+import each from "jest-each";
 
 class MockAppStore<T> {
   getState() {
@@ -914,6 +922,9 @@ describe('VFModule Control Generator', () => {
   let injector;
   let service: VfModuleControlGenerator;
   let httpMock: HttpTestingController;
+  let store : NgRedux<AppState>;
+  let mockFeatureFlagsService: FeatureFlagsService = mock(FeatureFlagsService);
+
 
   beforeAll(done => (async () => {
     TestBed.configureTestingModule({
@@ -925,7 +936,8 @@ describe('VFModule Control Generator', () => {
         AaiService,
         FormBuilder,
         LogService,
-        {provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
+        SharedTreeService,
+        {provide: FeatureFlagsService, useValue: instance(mockFeatureFlagsService)},
         {provide: NgRedux, useClass: MockAppStore}]
     });
     await TestBed.compileComponents();
@@ -933,10 +945,28 @@ describe('VFModule Control Generator', () => {
     injector = getTestBed();
     service = injector.get(VfModuleControlGenerator);
     httpMock = injector.get(HttpTestingController);
+    store = injector.get(NgRedux);
     jest.spyOn(console, 'error');
 
   })().then(done).catch(done.fail));
 
+  let formControlsWithoutLcpRegionTenantLegacy : string[] =
+    [FormControlNames.INSTANCE_NAME,
+      FormControlNames.VOLUME_GROUP_NAME,
+      FormControlNames.ROLLBACK_ON_FAILURE,
+      SDN_C_PRE_LOAD,];
+
+  let formControlsWithLcpRegionTenantLegacy : string[] =
+        [FormControlNames.INSTANCE_NAME,
+        FormControlNames.VOLUME_GROUP_NAME,
+        FormControlNames.LCPCLOUD_REGION_ID,
+        FormControlNames.LEGACY_REGION,
+        FormControlNames.TENANT_ID,
+        FormControlNames.ROLLBACK_ON_FAILURE,
+        SDN_C_PRE_LOAD,];
+
+
+
   test(' getMacroFormControls gets vnfStoreKey === null', () => {
     const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44";
     const vnfStoreKey: string = null;
@@ -1049,20 +1079,15 @@ describe('VFModule Control Generator', () => {
     expect(console.error).toHaveBeenCalled();
   });
 
-  test('getAlaCarteFormControls should return the correct order of controls', () => {
+  each([
+    [true, 4, formControlsWithoutLcpRegionTenantLegacy],
+    [false, 7,formControlsWithLcpRegionTenantLegacy]
+  ]).
+  test('getAlaCarteFormControls should return the correct order of controls', (flag: boolean, controlAmount: number, orderedControls: string[]) => {
+    when(mockFeatureFlagsService.getFlagState(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)).thenReturn(flag);
     const controls:FormControlModel[] = getAlaCarteFormControls();
 
-    const orderedControls : string[] = [
-      FormControlNames.INSTANCE_NAME,
-      FormControlNames.VOLUME_GROUP_NAME,
-      FormControlNames.LCPCLOUD_REGION_ID,
-      FormControlNames.LEGACY_REGION,
-      FormControlNames.TENANT_ID,
-      FormControlNames.ROLLBACK_ON_FAILURE,
-      SDN_C_PRE_LOAD,
-    ];
-
-    expect(controls.length).toEqual(7);
+    expect(controls.length).toEqual(controlAmount);
     for(let i = 0 ; i < orderedControls.length ; i++) {
      expect(controls[i].controlName).toEqual(orderedControls[i]);
     }
@@ -1084,26 +1109,6 @@ describe('VFModule Control Generator', () => {
     return controls;
   }
 
-  test('getAlaCarteFormControls responce with wrong order of controls', () => {
-    const controls:FormControlModel[] = getAlaCarteFormControls();
-
-    const orderedControls : string[] = [
-      FormControlNames.INSTANCE_NAME,
-      FormControlNames.VOLUME_GROUP_NAME,
-      FormControlNames.LCPCLOUD_REGION_ID,
-      FormControlNames.TENANT_ID, // TENANT_ID must be after LEGACY_REGION
-      FormControlNames.LEGACY_REGION,
-      FormControlNames.ROLLBACK_ON_FAILURE,
-      SDN_C_PRE_LOAD,
-    ];
-
-    for(let i = 0 ; i < orderedControls.length ; i++) {
-      if (controls[i].controlName === 'legacyRegion') {
-        expect(orderedControls[i]).toEqual('tenantId');
-      }
-    }
-  });
-
   test('getMacroFormControls should return the correct order of controls', () => {
     const serviceId: string = "6e59c5de-f052-46fa-aa7e-2fca9d674c44";
     const vnfStoreKey: string = 'VF_vGeraldine 0';
@@ -1140,23 +1145,28 @@ describe('VFModule Control Generator', () => {
     expect(instanceNameValidator.validatorArg).toEqual(/^[a-zA-Z0-9._-]*$/);
   });
 
-  test(' getAlaCarteFormControls gets null service', () => {
-    const controls:FormControlModel[] = getAlaCarteFormControls();
-    expect(controls.length).toEqual(7);
 
-    const orderedControls : string[] = [
-      FormControlNames.INSTANCE_NAME,
-      FormControlNames.VOLUME_GROUP_NAME,
-      FormControlNames.LCPCLOUD_REGION_ID,
-      FormControlNames.LEGACY_REGION,
-      FormControlNames.TENANT_ID,
-      FormControlNames.ROLLBACK_ON_FAILURE,
-      SDN_C_PRE_LOAD,
-    ];
+  test('when flag is active - response should contains upload file', ()=>{
+    spyOn(store, 'getState').and.returnValue( {
+      "global": {
+        "flags": {
+          "FLAG_2006_VFM_SDNC_PRELOAD_FILES" : true
+        }
+      }
+    });
+
+    const extraContent = service.getSdncExtraContents();
+    console.log("extraContent", extraContent);
+    const uploadFileData = <any>extraContent[0];
+
+    expect(uploadFileData.type).toEqual('UPLOAD_FILE');
+    expect(uploadFileData.dataTestId).toEqual('sdnc_pereload_upload_link');
+    expect(uploadFileData.uploadMethod).toBeDefined();
+    expect(uploadFileData.isDisabled).toBeDefined();
+    expect(uploadFileData.onSuccess).toBeDefined();
+    expect(uploadFileData.onFailed).toBeDefined();
+
+  })
 
-    for(let i = 0 ; i < orderedControls.length ; i++) {
-      expect(controls[i].controlName).toEqual(orderedControls[i]);
-    }
-  });
 });
 
index 60ffc3e..b614ecf 100644 (file)
@@ -3,7 +3,7 @@ import {GenericFormService} from "../../generic-form.service";
 import {AaiService} from "../../../../services/aaiService/aai.service";
 import {NgRedux} from "@angular-redux/store";
 import {HttpClient} from "@angular/common/http";
-import {ControlGeneratorUtil} from "../control.generator.util.service";
+import {ControlGeneratorUtil, SDN_C_PRE_LOAD} from "../control.generator.util.service";
 import {
   CustomValidatorOptions,
   FormControlModel,
@@ -20,6 +20,10 @@ import {VNFModel} from "../../../../models/vnfModel";
 import {VnfInstance} from "../../../../models/vnfInstance";
 import * as _ from 'lodash';
 import {SharedControllersService} from "../sharedControlles/shared.controllers.service";
+import {MessageModal} from "../../../messageModal/message-modal.service";
+import {ButtonType} from "../../../customModal/models/button.type";
+import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
+import {FeatureFlagsService, Features} from "../../../../services/featureFlag/feature-flags.service";
 
 export enum FormControlNames {
   INSTANCE_NAME = 'instanceName',
@@ -35,15 +39,17 @@ export enum FormControlNames {
 export class VfModuleControlGenerator {
   aaiService: AaiService;
   vfModuleModel: VfModule;
-  isUpdateMode : boolean;
+  isUpdateMode: boolean;
 
   constructor(private genericFormService: GenericFormService,
               private _basicControlGenerator: ControlGeneratorUtil,
               private _sharedControllersService: SharedControllersService,
+              private _sharedTreeService: SharedTreeService,
               private store: NgRedux<AppState>,
               private http: HttpClient,
               private _aaiService: AaiService,
-              private _logService: LogService) {
+              private _logService: LogService,
+              private _featureFlagsService:FeatureFlagsService) {
     this.aaiService = _aaiService;
   }
 
@@ -52,7 +58,7 @@ export class VfModuleControlGenerator {
     if (isUpdateMode && this.store.getState().service.serviceInstance[serviceId] &&
       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs, vnfStoreKey) &&
       _.has(this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules, UUIDData['modelName'])) {
-       vfModuleInstance = Object.assign({},this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]);
+      vfModuleInstance = Object.assign({}, this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey].vfModules[UUIDData['modelName']][UUIDData['vFModuleStoreKey']]);
     }
     return vfModuleInstance;
   };
@@ -63,11 +69,11 @@ export class VfModuleControlGenerator {
     return vfModule;
   }
 
-  getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
+  getMacroFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] {
     this.isUpdateMode = isUpdateMode;
     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
-      if(isUpdateMode){
+      if (isUpdateMode) {
         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
         return [];
       }
@@ -76,21 +82,28 @@ export class VfModuleControlGenerator {
     const vfModuleInstance = this._basicControlGenerator.retrieveInstanceIfUpdateMode(this.store, this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode));
     const vfModuleModel = this.vfModuleModel;
     const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey];
-    const vnfModelName: string = vnf.originalName;
-    const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]);
+    const vnfModel = this.newVNFModel(serviceId, vnf);
 
     let result: FormControlModel[] = [];
 
     if (!_.isNil(vfModuleModel)) {
       result = this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, false);
     }
-    if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
+    if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
       result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
     }
     return result;
   }
 
-  pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean) :FormControlModel[]{
+  private newVNFModel(serviceId: string, vnf: VnfInstance) {
+    const vnfModelName: string = this._sharedTreeService.modelUniqueNameOrId(vnf);
+
+    const serviceModelFromHierarchy = this.store.getState().service.serviceHierarchy[serviceId];
+    const model = this._sharedTreeService.modelByIdentifiers(serviceModelFromHierarchy, "vnfs", vnfModelName);
+    return new VNFModel(model);
+  }
+
+  pushInstanceAndVGToForm(result: FormControlModel[], vfModuleElement: any, serviceId: string, vnfModel: any, isALaCarte: boolean): FormControlModel[] {
     result.push(this.getInstanceName(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming));
     if (this.vfModuleModel.volumeGroupAllowed) {
       result.push(this.getVolumeGroupData(vfModuleElement, serviceId, vnfModel.isEcompGeneratedNaming, isALaCarte));
@@ -98,46 +111,85 @@ export class VfModuleControlGenerator {
     return result;
   }
 
-  getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData : Object, isUpdateMode: boolean): FormControlModel[] {
+  getAlaCarteFormControls(serviceId: string, vnfStoreKey: string, vfModuleStoreKey: string, uuidData: Object, isUpdateMode: boolean): FormControlModel[] {
     this.isUpdateMode = isUpdateMode;
     this.extractVfAccordingToVfModuleUuid(serviceId, uuidData);
     if (_.isNil(serviceId) || _.isNil(vnfStoreKey) || _.isNil(vfModuleStoreKey)) {
-      if(isUpdateMode){
+      if (isUpdateMode) {
         this._logService.error('should provide serviceId, vfModuleStoreKey, vnfStoreKey', serviceId);
         return [];
       }
     }
-    const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey] ;
-    const vnfModelName: string = vnf.originalName;
-    const vnfModel = new VNFModel(this.store.getState().service.serviceHierarchy[serviceId].vnfs[vnfModelName]);
+    const vnf: VnfInstance = this.store.getState().service.serviceInstance[serviceId].vnfs[vnfStoreKey];
+    const vnfModel = this.newVNFModel(serviceId, vnf);
 
     const vfModuleInstance = this._basicControlGenerator.retrieveInstanceIfUpdateMode(this.store, this.getVfModuleInstance(serviceId, vnfStoreKey, uuidData, isUpdateMode));
     let result: FormControlModel[] = [];
     this.pushInstanceAndVGToForm(result, vfModuleInstance, serviceId, vnfModel, true);
-    result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vfModuleInstance, result));
-    result.push(this._sharedControllersService.getLegacyRegion(vfModuleInstance));
-    result.push(this._sharedControllersService.getTenantControl(serviceId, vfModuleInstance));
+    if( !this._featureFlagsService.getFlagState(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)) {
+      result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vfModuleInstance, result));
+      result.push(this._sharedControllersService.getLegacyRegion(vfModuleInstance));
+      result.push(this._sharedControllersService.getTenantControl(serviceId, vfModuleInstance));
+    }
     result.push(this._sharedControllersService.getRollbackOnFailureControl(vfModuleInstance));
-    result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance));
-    if(this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
+    result.push(this._sharedControllersService.getSDNCControl(vfModuleInstance, this.getSdncExtraContents()));
+    if (this.store.getState().global.flags['FLAG_SUPPLEMENTARY_FILE']) {
       result = this._basicControlGenerator.concatSupplementaryFile(result, vfModuleInstance);
     }
     return result;
   }
 
-  getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
-    let formControlModel:FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel);
-    formControlModel.onBlur = (event, form : FormGroup) => {
-        if(!_.isNil(form.controls['volumeGroupName'])&& event.target.value.length > 0){
-          form.controls['volumeGroupName'].setValue(event.target.value + "_vol");
+  getSdncExtraContents() : object[] {
+    return _.compact([
+      !!this.store.getState().global.flags['FLAG_2006_VFM_SDNC_PRELOAD_FILES'] ? {
+        type: 'UPLOAD_FILE',
+        dataTestId: 'sdnc_pereload_upload_link',
+        uploadMethod: (form: FormGroup) : Promise<boolean> => {
+          // this -> files item
+          return this._aaiService.sdncPreload().toPromise()
+            .then((response : boolean)=>{
+              return response;
+            }).catch(err => {
+              return false;
+            });
+        },
+        isDisabled: (form: FormGroup): boolean => {
+          return !form.controls[SDN_C_PRE_LOAD].value;
+        },
+        onSuccess: (form: FormGroup): void => {
+          MessageModal.showMessageModal({
+            text: 'The pre-load file(s) have been uploaded successfully.',
+            type: "success",
+            title: 'Success',
+            buttons: [{type: ButtonType.success, size: 'large', text: 'OK', closeModal: true}]
+          })
+        },
+        onFailed: (form: FormGroup) : void=> {
+          MessageModal.showMessageModal({
+            text: 'Failed to upload one or more of the files, please retry.',
+            type: "error",
+            title: 'Failure',
+            buttons: [{type: ButtonType.error, size: 'large', text: 'OK', closeModal: true}]
+          })
         }
-      };
+      } : null
+    ]);
+  }
+
+
+  getInstanceName(instance: any, serviceId: string, isEcompGeneratedNaming: boolean): FormControlModel {
+    let formControlModel: FormControlModel = this._sharedControllersService.getInstanceNameController(instance, serviceId, isEcompGeneratedNaming, this.vfModuleModel);
+    formControlModel.onBlur = (event, form: FormGroup) => {
+      if (!_.isNil(form.controls['volumeGroupName']) && event.target.value.length > 0) {
+        form.controls['volumeGroupName'].setValue(event.target.value + "_vol");
+      }
+    };
 
     return formControlModel;
   }
 
   getDefaultVolumeGroupName(instance: any, isEcompGeneratedNaming: boolean): string {
-    if ((!_.isNil(instance) && instance.volumeGroupName))  {
+    if ((!_.isNil(instance) && instance.volumeGroupName)) {
       return instance.volumeGroupName;
     }
     if (isEcompGeneratedNaming) {
@@ -157,12 +209,12 @@ export class VfModuleControlGenerator {
       displayName: 'Volume Group Name',
       dataTestId: 'volumeGroupName',
       validations: validations,
-      tooltip : 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
-                'When empty, the module is created without a Volume Group.',
-      isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming,isALaCarte),
+      tooltip: 'When filled, VID will create a Volume Group by this name and associate with this module.\n' +
+        'When empty, the module is created without a Volume Group.',
+      isVisible: this.shouldVGNameBeVisible(isEcompGeneratedNaming, isALaCarte),
       value: this.getDefaultVolumeGroupName(instance, isEcompGeneratedNaming),
       onKeypress: (event) => {
-        const pattern:RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX;
+        const pattern: RegExp = ControlGeneratorUtil.INSTANCE_NAME_REG_EX;
         if (pattern) {
           if (!pattern.test(event['key'])) {
             event.preventDefault();
@@ -174,7 +226,7 @@ export class VfModuleControlGenerator {
   }
 
   private shouldVGNameBeVisible(isEcompGeneratedNaming: boolean, isALaCarte: boolean) {
-    if((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte){
+    if ((!isALaCarte && !isEcompGeneratedNaming) || isALaCarte) {
       return true;
     }
     return false;
index 018130e..4572fa4 100644 (file)
@@ -957,7 +957,8 @@ describe('VNF Control Generator', () => {
       FormControlNames.INSTANCE_NAME,
       FormControlNames.LCPCLOUD_REGION_ID,
       FormControlNames.TENANT_ID,
-      'platformName'
+      'platformName',
+      FormControlNames.PRODUCT_FAMILY_ID
     ];
 
     for(let i = 0 ; i < mandatoryControls.length ; i++){
index 14b31b4..169780b 100644 (file)
@@ -50,7 +50,7 @@ export class VnfControlGenerator {
 
     if (!_.isNil(vnfModel)) {
       result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming));
-      result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, false));
+      result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, true));
       result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result));
       result.push(this._sharedControllersService.getLegacyRegion(vnfInstance));
       result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance));
@@ -74,7 +74,7 @@ export class VnfControlGenerator {
     if (!_.isNil(vnfModel)) {
       const flags = this.store.getState().global.flags;
       result.push(this.getInstanceName(vnfInstance, serviceId, vnfName, vnfModel.isEcompGeneratedNaming));
-      result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, false));
+      result.push(this._sharedControllersService.getProductFamilyControl(vnfInstance, result, true));
       result.push(this._sharedControllersService.getLcpRegionControl(serviceId, vnfInstance, result));
       result.push(this._sharedControllersService.getLegacyRegion(vnfInstance));
       result.push(this._sharedControllersService.getTenantControl(serviceId, vnfInstance));
index edf8682..627f642 100644 (file)
@@ -3,7 +3,7 @@
     <div *ngFor="let formControl of formControls" class="form-conrtols">
       <div [ngSwitch]="formControl.type">
         <form-control-input  *ngSwitchCase="'INPUT'"   [data]="formControl" [form]="dynamicFormGroup"></form-control-input>
-        <checkbox-form-control *ngSwitchCase="'CHECKBOX'"  [data]="formControl" [form]="dynamicFormGroup" ></checkbox-form-control>
+        <checkbox-form-control *ngSwitchCase="'CHECKBOX'"  [data]="formControl" [form]="dynamicFormGroup"></checkbox-form-control>
         <dropdown-form-control *ngSwitchCase="'DROPDOWN'" [data]="formControl" [form]="dynamicFormGroup" ></dropdown-form-control>
         <file-form-control *ngSwitchCase="'FILE'" [data]="formControl" [form]="dynamicFormGroup"></file-form-control>
         <multiselect-form-control *ngSwitchCase="'MULTI_SELECT'"
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.html
new file mode 100644 (file)
index 0000000..6f59c0c
--- /dev/null
@@ -0,0 +1,15 @@
+<div>
+  <a [attr.data-tests-id]="uploadFilesModel.dataTestId"
+     (click)="uploadFilesTrigger()"
+     href="javascript:void(0)"
+     class="upload-text"
+     [class.disabled]="uploadFilesModel.isDisabled &&  uploadFilesModel.isDisabled(form)">{{uploadFilesModel.uploadText || 'Upload'}}</a>
+  <span class="hide-span">
+     <input
+       type="file"
+       #fileInput
+       ng2FileSelect
+       [uploader]="uploader"
+       [attr.data-tests-id]="uploadFilesModel.dataTestId + '-input'"/>
+  </span>
+</div>
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.scss
new file mode 100644 (file)
index 0000000..ce9e14f
--- /dev/null
@@ -0,0 +1,23 @@
+.upload-text {
+  margin-left: 30px;
+  font-family: OpenSans-Semibold;
+  font-size: 14px;
+  line-height: 23px;
+}
+
+a.disabled {
+  color: gray;
+  cursor: not-allowed;
+  text-decoration: underline;
+}
+
+.hide-span {
+  visibility: hidden;
+  position: absolute;
+  overflow: hidden;
+  width: 0px;
+  height: 0px;
+  border: none;
+  margin: 0;
+  padding: 0
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component.ts
new file mode 100644 (file)
index 0000000..803d5d0
--- /dev/null
@@ -0,0 +1,41 @@
+import {Component, ElementRef, Input, OnInit, ViewChild} from "@angular/core";
+import {FileItem, FileUploader} from "ng2-file-upload";
+import {UploadFilesLinkModel} from "./upload-files-link.model";
+import {FormGroup} from "@angular/forms";
+
+@Component({
+  selector: 'upload-files',
+  templateUrl: './upload-files-link.component.html',
+  styleUrls: ['./upload-files-link.component.scss']
+})
+export class UploadFilesLinkComponent implements OnInit {
+  uploader: FileUploader;
+  @Input() uploadFilesModel: UploadFilesLinkModel;
+  @Input() form: FormGroup;
+  @ViewChild('fileInput', {static: false}) fileInput: ElementRef;
+
+  ngOnInit(): void {
+    this.uploader = new FileUploader({});
+
+    this.uploader.onAfterAddingAll = async (files: FileItem[]) => {
+      const result = await this.uploadFilesModel.uploadMethod.call(files, this.form);
+      if (result && this.uploadFilesModel.onSuccess) {
+        this.uploadFilesModel.onSuccess.call(this.form);
+      } else if (!result && this.uploadFilesModel.onFailed) {
+        this.uploadFilesModel.onFailed.call(this.form);
+      }
+      this.uploadFilesModel.uploadText = result ? 'Upload another' : 'Upload'
+    };
+    this.resetUpload();
+  }
+
+  resetUpload(): void {
+    this.fileInput.nativeElement.value = '';
+  }
+
+  uploadFilesTrigger() {
+    if (this.uploadFilesModel.isDisabled && !this.uploadFilesModel.isDisabled(this.form)) {
+      this.fileInput.nativeElement.click();
+    }
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts b/vid-webpack-master/src/app/shared/components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.model.ts
new file mode 100644 (file)
index 0000000..beb54f4
--- /dev/null
@@ -0,0 +1,30 @@
+import {FileItem} from "ng2-file-upload";
+
+export class UploadFilesLinkModel {
+  uploadText?: string;
+
+  /*********************************************************************
+   Implement success method - run after uploadMethod return true result
+   **********************************************************************/
+  onSuccess?: (...args) => void;
+
+  /*********************************************************************
+   Implement failed method - run after uploadMethod return false result
+   **********************************************************************/
+  onFailed?: (...args) => void;
+
+  /*********************************************************************************
+   Implement upload method and return the upload result status (false/true)
+   *********************************************************************************/
+  uploadMethod: (file: FileItem[], ...args) => Promise<boolean>;
+
+  /********************************
+   Should upload file be disabled
+   ********************************/
+  isDisabled?: (...args) => boolean;
+
+  /********************************
+   a tag data test id
+   ********************************/
+  dataTestId : string;
+}
index 6bb1ff1..0313574 100644 (file)
           type="button" class="btn btn-success submit"
           (click)="openTemplateModal()"
         ><span>Template</span></button>
-        <button
-          *ngIf="isShowPreviousInstantiationBtn"
-          [attr.data-tests-id]="'ShowPreviousInstancesButton'"
-          type="button" class="btn btn-success submit"
-          (click)="formPopupDetails.onOtherAction(formPopupDetails.that, dynamicForm)"
-        ><span>Previous Instantiation</span></button>
         <button
           [attr.data-tests-id]="'cancelButton'"
           type="button" class="btn btn-default cancel"
index 9063e67..7368dd6 100644 (file)
@@ -47,7 +47,6 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
   type: PopupType;
   uuidData: UUIDData;
   showTemplateBtn: boolean = false;
-  isShowPreviousInstantiationBtn: boolean = false;
   isUpdateMode: boolean;
   node: ITreeNode = null;
   hasGeneralApiError: boolean = false;
@@ -89,7 +88,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
       .subscribe(params => {
         this.serviceModelId = params['serviceModelId'];
         if (this.serviceModelId && params['isCreate'] == "true") {
-          this.onInitForCreateNewServicePopup(params['hasTemplate']);
+          this.onInitForCreateNewServicePopup(params['isInstantiationTemplateExists']);
         }
       });
 
@@ -107,7 +106,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
     }
   }
 
-  private onInitForCreateNewServicePopup(hasTemplate : boolean) {
+  private onInitForCreateNewServicePopup(isInstantiationTemplateExists : boolean) {
     this._genericFormPopupService.initReduxOnCreateNewService().then((serviceModelId: string) => {
       this.uuidData = <any>{
         bulkSize: 1,
@@ -117,8 +116,7 @@ export class GenericFormPopupComponent extends DialogComponent<PopupModel, boole
         popupService: this._servicePopupService,
       };
 
-      this.showTemplateBtn = this._genericFormPopupService.shouldShowTemplateBtn(hasTemplate);
-      this.isShowPreviousInstantiationBtn = !!this._store.getState().global.flags["FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER"];
+      this.showTemplateBtn = this._genericFormPopupService.shouldShowTemplateBtn(isInstantiationTemplateExists);
 
       this.uuidData.popupService.closeDialogEvent.subscribe((that) => {
         this.closeDialog(that);
index 53f345a..e69cd56 100644 (file)
@@ -24,6 +24,7 @@ import {VfModuleUpgradePopupService} from "./genericFormServices/vfModuleUpgrade
 import {SharedControllersService} from "../genericForm/formControlsServices/sharedControlles/shared.controllers.service";
 import {AppState} from "../../store/reducers";
 import each from 'jest-each';
+import {SharedTreeService} from "../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
 
 class MockAppStore<T>{
   getState() {
@@ -977,6 +978,7 @@ describe('Generic Form popup Service', () => {
         VfModuleUpgradePopupService,
         VfModuleControlGenerator,
         FeatureFlagsService,
+        SharedTreeService,
         {provide: ActivatedRoute, useClass: ActivatedRouteMock},
         {provide: NgRedux, useClass: MockAppStore}]
     });
@@ -1074,14 +1076,14 @@ describe('Generic Form popup Service', () => {
 
 
   const shouldShowTemplateBtnDataProvider = [
-    ['shouldShowTemplateBtn : should return true if flag is true and has template', true , true, true],
-    ['shouldShowTemplateBtn : should return false if flag is false and has template',false , true, false],
-    ['shouldShowTemplateBtn : should return false if flag is true and has no template',true , false, false],
-    ['shouldShowTemplateBtn : should return false if flag is false and has no template',false , false, false]];
-  each(shouldShowTemplateBtnDataProvider).test('%s', (desc : string, flag : boolean, hasTemplate : boolean, expected : boolean ) => {
+    ['shouldShowTemplateBtn : should return true if flag is true and has instantiation template', true , true, true],
+    ['shouldShowTemplateBtn : should return false if flag is false and has instantiation template',false , true, false],
+    ['shouldShowTemplateBtn : should return false if flag is true and has no instantiation template',true , false, false],
+    ['shouldShowTemplateBtn : should return false if flag is false and has no instantiation template',false , false, false]];
+  each(shouldShowTemplateBtnDataProvider).test('%s', (desc : string, flag : boolean, isInstantiationTemplateExists : boolean, expected : boolean ) => {
     spyOn(_featureFlagsService, 'getFlagState').and.returnValue(flag)
 
-    const result: boolean = service.shouldShowTemplateBtn(hasTemplate);
+    const result: boolean = service.shouldShowTemplateBtn(isInstantiationTemplateExists);
     expect(result).toEqual(expected);
   });
 });
index 2998ba9..e3cdaef 100644 (file)
@@ -95,10 +95,10 @@ export class GenericFormPopupService {
 
 
 
-  shouldShowTemplateBtn = (hasTemplate: boolean) : boolean => {
+  shouldShowTemplateBtn = (isInstantiationTemplateExists: boolean) : boolean => {
     const instantiationTemplateFlag =  this._featureFlagsService.getFlagState(Features.FLAG_2004_INSTANTIATION_TEMPLATES_POPUP);
     if(instantiationTemplateFlag){
-      return hasTemplate;
+      return isInstantiationTemplateExists;
     }
     return false;
   }
index 9bcc02d..1343892 100644 (file)
@@ -11,9 +11,9 @@ import {IframeService} from "../../../utils/iframe.service";
 import {DefaultDataGeneratorService} from "../../../services/defaultDataServiceGenerator/default.data.generator.service";
 import {FormControlModel} from "../../../models/formControlModels/formControl.model";
 import {BasicPopupService} from "./basic.popup.service";
-import {SdcUiServices} from "onap-ui-angular";
 import {FeatureFlagsService} from "../../../services/featureFlag/feature-flags.service";
 import {getTestBed, TestBed} from "@angular/core/testing";
+import {ModalService} from "../../customModal/services/modal.service";
 
 class MockAppStore<T> {}
 
@@ -1996,7 +1996,7 @@ describe('Basic popup service', () => {
         {provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockReduxStore},
         {provide: HttpClient, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
index 34d6850..a32320e 100644 (file)
@@ -14,6 +14,7 @@ import {BasicPopupService} from "../basic.popup.service";
 import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
 import {getTestBed, TestBed} from "@angular/core/testing";
 import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../customModal/services/modal.service";
 
 class MockAppStore<T> {}
 
@@ -2001,7 +2002,7 @@ describe('Network popup service', () => {
         {provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockReduxStore},
         {provide: HttpClient, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
index 3a106ec..13b72f0 100644 (file)
@@ -11,10 +11,10 @@ import {BasicPopupService} from "../basic.popup.service";
 import {ServicePopupService} from "./service.popup.service";
 import {ServiceControlGenerator} from "../../../genericForm/formControlsServices/service.control.generator";
 import {FormControlModel} from "../../../../models/formControlModels/formControl.model";
-import {SdcUiServices} from "onap-ui-angular";
 import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
 import {getTestBed, TestBed} from "@angular/core/testing";
 import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../customModal/services/modal.service";
 
 class MockModalService<T> {}
 
@@ -2067,7 +2067,7 @@ describe('Service popup service', () => {
         {provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockReduxStore},
         {provide: HttpClient, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
@@ -2142,33 +2142,6 @@ describe('Service popup service', () => {
     expect(service.closeDialogEvent.next).toHaveBeenCalledWith(that);
   });
 
-  test('showPreviousInstantiations should trigger postMessage', () => {
-    let that = <any>{
-      parentElementClassName: 'content',
-      _iframeService: iframeService,
-      resetPopupData : () =>{      },
-      serviceModel:{
-        uuid:'1111'
-      }
-
-    };
-
-    let expectedMessage= {
-      eventId: 'showPreviousInstantiations',
-      data: {
-        serviceModelId: that.serviceModel.uuid
-      }
-    };
-
-    jest.spyOn(window.parent, 'postMessage');
-
-    service.showPreviousInstantiations(that, fb.group({}));
-
-    expect( window.parent.postMessage).toHaveBeenCalledWith(expectedMessage,"*")
-
-  });
-
-
 
   test('getDynamicInputs should return list of controls' ,() => {
     const result:  FormControlModel[] = service.getDynamicInputs('6b528779-44a3-4472-bdff-9cd15ec93450');
index d25ab2c..588d234 100644 (file)
@@ -61,9 +61,6 @@ export class ServicePopupService implements GenericPopupInterface {
       (that, form: FormGroup) => {that.onSubmit(that, form);},
       (that: any, form: FormGroup) => {
         that.onCancel(that, form);
-      },
-      (that: any, form: FormGroup) => {
-        that.showPreviousInstantiations(that, form);
       }
     );
   }
@@ -133,12 +130,6 @@ export class ServicePopupService implements GenericPopupInterface {
     this.onCancel(that, form);
   }
 
-  showPreviousInstantiations(that, form: FormGroup,): void {
-    const eventId = 'showPreviousInstantiations';
-    this.postMessageToWindowParent(eventId, that.serviceModel.uuid);
-    this.onCancel(that, form);
-  }
-
   private postMessageToWindowParent(eventId: string, serviceModelId:string) {
     window.parent.postMessage({
       eventId: eventId,
index b16c5bd..b8a5922 100644 (file)
@@ -10,10 +10,11 @@ import {DefaultDataGeneratorService} from "../../../../services/defaultDataServi
 import {BasicPopupService} from "../basic.popup.service";
 import {VfModulePopupService} from "./vfModule.popup.service";
 import {VfModuleControlGenerator} from "../../../genericForm/formControlsServices/vfModuleGenerator/vfModule.control.generator";
-import {SdcUiServices} from "onap-ui-angular";
 import {FeatureFlagsService} from "../../../../services/featureFlag/feature-flags.service";
 import {getTestBed, TestBed} from "@angular/core/testing";
 import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../customModal/services/modal.service";
+import {SharedTreeService} from "../../../../../drawingBoard/service-planning/objectsToTree/shared.tree.service";
 
 class MockModalService<T> {}
 
@@ -1993,10 +1994,11 @@ describe('VFModule popup service', () => {
         AaiService,
         LogService,
         BasicPopupService,
+        SharedTreeService,
         {provide:FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockReduxStore},
         {provide: HttpClient, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
index 2ca992f..578c37e 100644 (file)
@@ -1,10 +1,6 @@
 import {LogService} from "../../../../utils/log/log.service";
 import {NgRedux} from "@angular-redux/store";
-import {
-  ControlGeneratorUtil,
-  SDN_C_PRE_LOAD,
-  SUPPLEMENTARY_FILE
-} from "../../../genericForm/formControlsServices/control.generator.util.service";
+import {ControlGeneratorUtil, SDN_C_PRE_LOAD, SUPPLEMENTARY_FILE} from "../../../genericForm/formControlsServices/control.generator.util.service";
 import {AaiService} from "../../../../services/aaiService/aai.service";
 import {HttpClient} from "@angular/common/http";
 import {GenericFormService} from "../../../genericForm/generic-form.service";
@@ -26,6 +22,7 @@ import {ServiceActions} from "../../../../storeUtil/utils/service/service.action
 import {FormControlModel} from "../../../../models/formControlModels/formControl.model";
 import * as _ from "lodash";
 import {SharedControllersService} from "../../../genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {ModalService} from "../../../customModal/services/modal.service";
 
 class MockModalService<T> {}
 
@@ -87,7 +84,7 @@ describe('VFModule popup service', () => {
         {provide: FeatureFlagsService, useClass: MockFeatureFlagsService},
         {provide: NgRedux, useClass: MockReduxStore},
         {provide: HttpClient, useClass: MockAppStore},
-        {provide: SdcUiServices.ModalService, useClass: MockModalService}
+        {provide: ModalService, useClass: MockModalService}
       ]
     });
     await TestBed.compileComponents();
@@ -191,7 +188,7 @@ describe('VFModule popup service', () => {
     };
     form.controls = {
       supplementaryFile_hidden_content : {
-        value: '{"c": "c", "d": 1}'
+        value: '[{"name": "c", "value": "c"}, {"name": "d", "value": "1"}]'
         },
       supplementaryFile_hidden : {
         value: {
@@ -203,7 +200,7 @@ describe('VFModule popup service', () => {
     let expectedMergePayload = {
       a: "value",
       b: "another",
-      supplementaryFileContent: {c: "c", d: 1},
+      supplementaryFileContent: [{"name": "c", "value": "c"}, {"name": "d", "value": "1"}],
       supplementaryFileName: "name"
     };
 
index 84783c2..39c6da4 100644 (file)
@@ -56,7 +56,6 @@
             <th class="header-title" id="header-summary">Summary</th>
             <th class="header-title" id="header-region">Region</th>
             <th class="header-title" id="header-tenant">Tenant</th>
-            <th class="header-title" id="header-aicZone">AIC Zone</th>
           </tr>
           </thead>
           <tbody>
                 </custom-ellipsis>
               </div>
             </td>
-            <td>
-              <div>
-                <custom-ellipsis
-                  [dataTestId]="'aicZone-' + item.jobId"
-                  [id]="item.aicZone"
-                  [value]="item.aicZone"
-                  [breakWord]="true">
-                </custom-ellipsis>
-              </div>
-            </td>
           </tr>
           </tbody>
         </table>
index 61f75e8..a479e0c 100644 (file)
@@ -17,9 +17,6 @@ class ActivatedRouteMock<T> {
   }
 }
 
-//
-
-
 class MockAppStore {}
 
 describe('instantiation templates modal service', () => {
@@ -123,7 +120,6 @@ describe('instantiation templates modal service', () => {
     expect(tableRows[0].instantiationStatus).toEqual('FAILED');
     expect(tableRows[0].region).toEqual('hvf6 (AAA1)');
     expect(tableRows[0].tenant).toEqual('AIN Web Tool-15-D-SSPtestcustome');
-    expect(tableRows[0].aicZone).toEqual('VSDKYUTP-BAN1');
     expect(tableRows[0].jobId).toEqual('9f88fdb5-bb47-4bf3-8c5f-98f1ad0ec87c');
   });
 
@@ -136,6 +132,14 @@ describe('instantiation templates modal service', () => {
     expect(result.region).toEqual('regionId (OWNER)');
   });
 
+  test('getRegion if null should return empty string', () => {
+    let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({
+      owningEntityName: 'att-owner',
+      regionId: null
+    });
+    expect(result.region).toEqual('(OWNER)');
+  });
+
   test('getCloudOwner should not return owningEntityName if not exist', () => {
     let result: InstantiationTemplatesRowModel = new InstantiationTemplatesRowModel({owningEntityName: null, regionId: 'regionId'});
     expect(result.region).toEqual('regionId');
@@ -173,7 +177,7 @@ describe('instantiation templates modal service', () => {
 
     service.navigateToNewServiceModal(serviceModelId);
 
-    expect(_router.navigate).toBeCalledWith(["/servicePopup"], {"queryParams": {"isCreate": true, "serviceModelId": serviceModelId, hasTemplate : true}, "queryParamsHandling": "merge"});
+    expect(_router.navigate).toBeCalledWith(["/servicePopup"], {"queryParams": {"isCreate": true, "serviceModelId": serviceModelId, isInstantiationTemplateExists : true}, "queryParamsHandling": "merge"});
   })
 
 });
index c7c198f..5c092e9 100644 (file)
@@ -30,7 +30,7 @@ export class InstantiationTemplatesModalService {
 
 
   navigateToNewServiceModal(serviceModelId: string) {
-     this._router.navigate(['/servicePopup'], { queryParams: { serviceModelId: serviceModelId, isCreate:true, hasTemplate : true}, queryParamsHandling: 'merge' });
+     this._router.navigate(['/servicePopup'], { queryParams: { serviceModelId: serviceModelId, isCreate:true, isInstantiationTemplateExists : true}, queryParamsHandling: 'merge' });
   }
 
 }
index f2eda9d..56f76b3 100644 (file)
@@ -10,7 +10,6 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{
   readonly summary?: string;
   readonly region?: string;
   readonly tenant?: string;
-  readonly aicZone?: string;
 
   constructor(data) {
     super(data);
@@ -21,7 +20,6 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{
     this.summary = this.convertRequestSummaryFromMapToString(data.requestSummary);
     this.region = this.getRegion(data.regionId, data.owningEntityName);
     this.tenant = !_.isNil(data.tenantName) ? data.tenantName : null;
-    this.aicZone = !_.isNil(data.aicZoneName) ? data.aicZoneName : null;
   }
 
 
@@ -36,7 +34,8 @@ export class InstantiationTemplatesRowModel extends InstantiationBase{
 
   getRegion = (regionId: string, owningEntityName: string): string => {
     const convertOwning = !_.isNil(owningEntityName) ? `(${this.getCloudOwner(owningEntityName)})` : '';
-    return `${regionId} ${convertOwning}`.trim();
+    const region = !_.isNil(regionId) ? regionId : '';
+    return `${region} ${convertOwning}`.trim();
   };
 
 
index c610110..5251a0a 100644 (file)
@@ -30,7 +30,7 @@
 import { Component } from '@angular/core';
 import { MessageBoxData} from './messageBox.data';
 import { MessageBoxService } from './messageBox.service';
-import { SdcUiServices} from "onap-ui-angular";
+import {ModalService} from "../customModal/services/modal.service";
 
 @Component({
   selector: 'message-box',
@@ -38,9 +38,9 @@ import { SdcUiServices} from "onap-ui-angular";
 })
 
 export class MessageBoxComponent {
-  modalService: SdcUiServices.ModalService;
+  modalService: ModalService;
   isOpened : boolean = false;
-  constructor(modalService: SdcUiServices.ModalService, private _messageBoxService : MessageBoxService) {
+  constructor(modalService: ModalService, private _messageBoxService : MessageBoxService) {
     this.modalService = modalService;
 
     MessageBoxService.openModal.subscribe((messageBoxData: MessageBoxData) => {
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.model.ts
new file mode 100644 (file)
index 0000000..d291440
--- /dev/null
@@ -0,0 +1,15 @@
+import {ButtonType} from "../customModal/models/button.type";
+
+export class MessageModalModel {
+  title : string;
+  text : string;
+  type : 'error' | 'info' | 'success';
+  buttons :  {text: string, size: string, type : ButtonType, closeModal: boolean}[];
+
+  constructor( title : string, text : string, type , buttons : {text: string, size: string, type : ButtonType, closeModal: boolean}[]){
+    this.title = title;
+    this.text = text;
+    this.type = type;
+    this.buttons = buttons;
+  }
+}
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.spec.ts
new file mode 100644 (file)
index 0000000..ffaccb1
--- /dev/null
@@ -0,0 +1,56 @@
+import {MessageModal} from "./message-modal.service";
+import {getTestBed, TestBed} from "@angular/core/testing";
+import {SdcUiCommon} from "onap-ui-angular";
+import each from "jest-each";
+import {MessageBoxService} from "../messageBox/messageBox.service";
+import {MessageModalModel} from "./message-modal.model";
+import {MessageBoxData} from "../messageBox/messageBox.data";
+
+
+describe('Message Modal Service', () => {
+  let injector;
+  let service: MessageModal;
+
+  beforeAll(done => (async () => {
+    TestBed.configureTestingModule({
+      imports: [],
+      providers: [MessageModal]
+    });
+    await TestBed.compileComponents();
+
+    injector = getTestBed();
+    service = injector.get(MessageModal);
+  })().then(done).catch(done.fail));
+
+
+  each([
+    ["error", SdcUiCommon.ModalType.error],
+    ["info", SdcUiCommon.ModalType.info],
+    ["success", SdcUiCommon.ModalType.success]
+  ]).test('getModalType with type %s should return %s', (inputMessageType, expectedResult) => {
+
+    let message = {
+      type: inputMessageType
+    };
+
+    const type = MessageModal.getModalType(<any>message)
+    expect(type).toEqual(expectedResult);
+  });
+
+  test('showMessageModal should call open modal with all data' , async (done)=>{
+    spyOn(MessageBoxService.openModal, 'next');
+    let message : MessageModalModel  = new MessageModalModel('title', 'text',  "success", []);
+
+    MessageModal.showMessageModal(message);
+    setTimeout(()=>{
+      const messageBoxData = new MessageBoxData( message.title,
+        message.text,
+        SdcUiCommon.ModalType.success,
+        SdcUiCommon.ModalSize.medium,
+        message.buttons)
+      expect(MessageBoxService.openModal.next).toHaveBeenCalledWith(messageBoxData);
+      done();
+    }, 500)
+  });
+
+});
diff --git a/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts b/vid-webpack-master/src/app/shared/components/messageModal/message-modal.service.ts
new file mode 100644 (file)
index 0000000..e1f85bd
--- /dev/null
@@ -0,0 +1,39 @@
+import {Injectable} from "@angular/core";
+import {MessageBoxService} from '../messageBox/messageBox.service';
+import {MessageBoxData} from '../messageBox/messageBox.data';
+import {SdcUiCommon} from "onap-ui-angular";
+import {MessageModalModel} from "./message-modal.model";
+
+@Injectable()
+export class MessageModal {
+  static showMessageModal(message: MessageModalModel): void {
+    setTimeout(() => {
+        let messageBoxData: MessageBoxData = new MessageBoxData(
+          message.title,
+          message.text,
+          this.getModalType(message),
+          SdcUiCommon.ModalSize.medium,
+          message.buttons);
+        MessageBoxService.openModal.next(messageBoxData);
+      }
+      , 500);
+  };
+
+
+  static getModalType = (message: MessageModalModel): string => {
+    switch (message.type) {
+      case "error": {
+        return SdcUiCommon.ModalType.error
+      }
+      case "info": {
+        return  SdcUiCommon.ModalType.info;
+      }
+      case "success":  {
+        return  SdcUiCommon.ModalType.success;
+      }
+    }
+  };
+}
+
+
+
index 47f8490..7d9561c 100644 (file)
@@ -44,7 +44,7 @@ export class SearchElementsModalComponent extends DialogComponent<{ modalInforma
     })
   }
 
-  @ViewChild('ElementsTableComponent') membersTable;
+  @ViewChild('ElementsTableComponent', {static: false}) membersTable;
 
   ngOnInit(selectedRowsIds?: string[]): void {
     const genericModalHelper = this._store.getState().global.genericModalHelper;
index 238f769..f0a4da9 100644 (file)
@@ -1,6 +1,6 @@
-<sdc-loader name= "global"
+<custom-loader name= "global"
             #globalLoader
             [global] = "global"
             [size]="size"
-            [(active)] = "show"></sdc-loader>
+            [(active)] = "show"></custom-loader>
 
index 2e46424..2b5727b 100644 (file)
@@ -10,14 +10,14 @@ import * as _ from 'lodash';
 
 @Component({
   selector : 'vid-svg-icon',
-  template: `    
-      <svg-icon
+  template: `
+      <custom-icon
         [mode]="mode"
         [size]="size"
         [name]="name"
         [testId]="testId"
         [clickable]="clickable">
-    </svg-icon>
+    </custom-icon>
   `,
 
 
index f505b56..1675917 100644 (file)
@@ -1,11 +1,13 @@
 import {FormControlModel} from "./formControl.model";
 import {FormControlType} from "./formControlTypes.enum";
+import * as _ from "lodash";
 
 export class CheckboxFormControl extends FormControlModel{
-
+  extraContents : object[];
   constructor(data) {
     super(data);
     this.type = FormControlType.CHECKBOX;
     this.validations = [];
+    this.extraContents = !_.isNil(data.extraContents)  ? data.extraContents : null;
   }
 }
index 2411654..b3a53d9 100644 (file)
@@ -43,6 +43,7 @@ export class  FormControlModel {
     this.preventionsAttribute = data.preventionsAttribute || [];
     this.onBlur = function(){};
     this.onChange = data.onChange ? data.onChange: function () {}
+
   }
 
   isRequired() : boolean {
index 40d74d6..36704e2 100644 (file)
@@ -14,8 +14,6 @@ export class FormPopupDetails {
   modelInformationItems: ModelInformationItem[];
   onSubmit : (that : any, form: FormGroup , ...args) =>  void;
   onCancel : (that : any, form: FormGroup) => void;
-  onOtherAction: (that: any, form: FormGroup) => void;
-
 
   constructor(that : any,
               popupTypeName : PopupType ,
@@ -27,8 +25,7 @@ export class FormPopupDetails {
               dynamicInputsControlList : FormControlModel[],
               modelInformationItems : ModelInformationItem[],
               onSubmit : (that : any, form : FormGroup, ...args) =>  void,
-              onCancel: (that: any, form: FormGroup) => void,
-              onOtherAction?: (that: any, form: FormGroup) => void) {
+              onCancel: (that: any, form: FormGroup) => void) {
     this.title = title;
     this.leftSubTitle = leftSubTitle;
     this.rightSubTitle = rightSubTitle;
@@ -37,7 +34,6 @@ export class FormPopupDetails {
     this.modelInformationItems = modelInformationItems;
     this.onSubmit = onSubmit;
     this.onCancel = onCancel;
-    this.onOtherAction = onOtherAction;
     this.popupTypeName = popupTypeName;
     this.UUIDData = UUIDData;
     this.that = that;
index 9242add..39f5622 100644 (file)
@@ -3,6 +3,7 @@ import {NodeModel} from "./nodeModel";
 import {ServiceNodeTypes} from "./ServiceNodeTypes";
 import * as _ from 'lodash';
 import {ServiceInstanceActions} from "./serviceInstanceActions";
+
 export enum TreeLevel {
   Level_0 , Level_1, Level_2
 
@@ -16,6 +17,7 @@ interface TreeNodeInstanceInterface {
 export class TreeNodeModel {
   type: String;
   modelId: string;
+  modelInvariantId?: string;
   modelCustomizationId?: string;
   modelUniqueId?: string;
   id: string;
@@ -32,6 +34,7 @@ export class TreeNodeModel {
   instanceName?: string;
 
   constructor(instance: ChildNodeInstance, nodeModel: NodeModel){
+    this.modelInvariantId = nodeModel.invariantUuid;
     this.modelCustomizationId = nodeModel.customizationUuid;
     this.modelId = nodeModel.uuid;
     this.modelUniqueId = this.modelCustomizationId || this.modelId;
old mode 100644 (file)
new mode 100755 (executable)
index a850d55..3a05157
@@ -22,7 +22,6 @@ import {
   updateProductFamilies, updateUserId
 } from "../../storeUtil/utils/general/general.actions";
 import {createServiceInstance} from "../../storeUtil/utils/service/service.actions";
-import {delay, mapTo} from "rxjs/operators";
 
 const notFetchedAlready = (state: AppState): boolean => state.service.productFamilies !== null;
 
@@ -30,7 +29,6 @@ const notFetchedAlready = (state: AppState): boolean => state.service.productFam
 export class AAIEpics {
   constructor(private aaiService: AaiService) {
   }
-
   public createEpic() {
     return combineEpics(
         this.loadProductFamiliesEpic
@@ -49,7 +47,11 @@ export class AAIEpics {
 
   private loadProductFamiliesEpic = (action$, store) => action$
     .ofType(LOAD_PRODUCT_FAMILIES)
-    .switchMap(() => this.aaiService.getProductFamilies().map(data => updateProductFamilies(data)));
+    .switchMap(() =>
+      this.aaiService.getProductFamilies()
+        .map(data =>
+          updateProductFamilies(data)
+      ));
 
   private loadCategoryParameters = (action$, store) => action$
     .ofType(LOAD_CATEGORY_PARAMETERS)
@@ -64,7 +66,9 @@ export class AAIEpics {
   private loadServiceAccordingToUuid = (action$, store) => action$
     .ofType(LOAD_SERVICE_MDOEL_BY_UUID)
     .switchMap((action) => this.aaiService.getServiceModelById(action.modelId)
-      .map(data => createServiceInstance(action.uuid, data)));
+      .map(data =>
+        createServiceInstance(action.uuid, data))
+    );
 
   private loadUserId = (action$, store) => action$
     .ofType(LOAD_USER_ID)
index 1cc5593..9026a56 100644 (file)
@@ -44,6 +44,11 @@ export class AaiService {
 
   }
 
+  sdncPreload(): Observable<boolean> {
+    let pathQuery: string = Constants.Path.PRE_LOAD;
+    return this.http.post<boolean>(pathQuery, {})
+  }
+
   getServiceModelById = (serviceModelId: string): Observable<any> => {
     if (_.has(this.store.getState().service.serviceHierarchy, serviceModelId)) {
       return of(<any> JSON.parse(JSON.stringify(this.store.getState().service.serviceHierarchy[serviceModelId])));
index cccade8..5842662 100644 (file)
@@ -15,8 +15,11 @@ export enum Features {
   FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS ='FLAG_2002_VFM_UPGRADE_ADDITIONAL_OPTIONS',
   FLAG_2004_INSTANTIATION_STATUS_FILTER ='FLAG_2004_INSTANTIATION_STATUS_FILTER',
   FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE = 'FLAG_2004_CREATE_ANOTHER_INSTANCE_FROM_TEMPLATE',
-  FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER ='FLAG_2004_TEMP_BUTTON_TO_INSTANTIATION_STATUS_FILTER',
-  FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP'
+  FLAG_2006_VFM_SDNC_PRELOAD_FILES = 'FLAG_2006_VFM_SDNC_PRELOAD_FILES',
+  FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO = 'FLAG_MORE_AUDIT_INFO_LINK_ON_AUDIT_INFO',
+  FLAG_2004_INSTANTIATION_TEMPLATES_POPUP = 'FLAG_2004_INSTANTIATION_TEMPLATES_POPUP',
+  FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY= 'FLAG_2006_USER_PERMISSIONS_BY_OWNING_ENTITY',
+  FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF = 'FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF',
 }
 
 @Injectable()
index f95f861..bae7c11 100644 (file)
@@ -49,7 +49,6 @@ import {ServicePopupService} from "./components/genericFormPopup/genericFormServ
 import {GenericFormPopupService} from "./components/genericFormPopup/generic-form-popup.service";
 import {FormGeneralErrorsService} from "./components/formGeneralErrors/formGeneralErrors.service";
 import {VnfPopupService} from "./components/genericFormPopup/genericFormServices/vnf/vnf.popup.service";
-import {SdcUiComponentsModule, SdcUiServices} from "onap-ui-angular";
 import {SafePipe} from "./pipes/safe/safe.pipe";
 import {ViewEditResolver} from "./resolvers/viewEdit/viewEdit.resolver";
 import {FlagsResolve} from "./resolvers/flag/flag.resolver";
@@ -80,6 +79,24 @@ import {SearchFilterPipe} from "./pipes/searchFilter/search-filter.pipe";
 import {RecreateResolver} from "./resolvers/recreate/recreate.resolver";
 import {InstantiationTemplatesService} from "./services/templateService/instantiationTemplates.service";
 import {SharedControllersService} from "./components/genericForm/formControlsServices/sharedControlles/shared.controllers.service";
+import {DuplicateVnfComponent} from "../drawingBoard/service-planning/duplicate/duplicate-vnf.component";
+import {ModalService} from "./components/customModal/services/modal.service";
+import {CreateDynamicComponentService} from "./components/customModal/services/create-dynamic-component.service";
+import {ModalComponent} from "./components/customModal/modal.component";
+import {ModalCloseButtonComponent} from './components/customModal/components/modalCloseButton/modal-close-button.component';
+import {CustomButtonComponent} from "./components/customButton/custom-button.component";
+import {CustomModalButtonComponent} from "./components/customModal/components/modalButton/modal-button.component";
+import {CustomRippleClickAnimationDirective} from "./components/customModal/directives/ripple-click.animation.directive";
+import {LoaderComponent} from "./components/customLoader/custom-loader.component";
+import {LoaderService} from "./components/customLoader/custom-loader.service";
+import {SvgIconComponent} from "./components/customIcon/custom-icon.component";
+import {TooltipTemplateComponent} from "./components/customTooltip/custom-tooltip.component";
+import {TooltipDirective} from "./components/customTooltip/tooltip.directive";
+import {SdcUiComponentsModule} from "onap-ui-angular";
+import {UploadFilesLinkComponent} from "./components/genericForm/genericFormSharedComponent/uploadFiles/upload-files-link.component";
+import { FileUploadModule } from 'ng2-file-upload';
+import {MessageModal} from "./components/messageModal/message-modal.service";
+
 
 
 @NgModule({
@@ -92,12 +109,13 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     FeatureFlagModule.forRoot(),
     FormsModule,
     ReactiveFormsModule,
-    TooltipModule,
     SdcUiComponentsModule,
+    TooltipModule,
     AngularMultiSelectModule,
     BootstrapModalModule,
     DataTableModule,
-    ModalModule.forRoot()
+    ModalModule.forRoot(),
+    FileUploadModule
   ],
   declarations: [
     PopoverComponent,
@@ -110,6 +128,8 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     NumberFormControlComponent,
     InputPreventionPatternDirective,
     ClickOutsideDirective,
+    TooltipDirective,
+    CustomRippleClickAnimationDirective,
     FormGeneralErrorsComponent,
     SpinnerComponent,
     NoContentMessageAndIconComponent,
@@ -133,7 +153,15 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     ErrorMsgComponent,
     DynamicInputsComponent,
     DynamicInputLabelPipe,
-    InstantiationTemplatesModalComponent
+    InstantiationTemplatesModalComponent,
+    ModalComponent,
+    ModalCloseButtonComponent,
+    CustomButtonComponent,
+    CustomModalButtonComponent,
+    LoaderComponent,
+    SvgIconComponent,
+    TooltipTemplateComponent,
+    UploadFilesLinkComponent
   ],
   exports: [
     PopoverComponent,
@@ -142,7 +170,9 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     FormControlErrorComponent,
     DropdownFormControlComponent,
     InputPreventionPatternDirective,
+    CustomRippleClickAnimationDirective,
     ClickOutsideDirective,
+    TooltipDirective,
     FormGeneralErrorsComponent,
     SpinnerComponent,
     NoContentMessageAndIconComponent,
@@ -165,18 +195,29 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     ErrorMsgComponent,
     SvgComponent,
     DynamicInputsComponent,
-    DynamicInputLabelPipe
+    DynamicInputLabelPipe,
+    ModalComponent,
+    ModalCloseButtonComponent,
+    CustomButtonComponent,
+    CustomModalButtonComponent,
+    LoaderComponent,
+    SvgIconComponent,
+    TooltipTemplateComponent,
+    UploadFilesLinkComponent
   ],
   entryComponents : [
     GenericFormPopupComponent,
     SearchElementsModalComponent,
-    InstantiationTemplatesModalComponent
+    InstantiationTemplatesModalComponent,
+    DuplicateVnfComponent,
+    ModalComponent
   ],
   providers: [
     ServiceInfoService,
     MessageBoxService,
-    SdcUiServices.ModalService,
-    SdcUiServices.LoaderService,
+    CreateDynamicComponentService,
+    ModalService,
+    LoaderService,
     HttpInterceptorService,
     IframeService,
     DefaultDataGeneratorService,
@@ -212,7 +253,9 @@ import {SharedControllersService} from "./components/genericForm/formControlsSer
     SearchFilterPipe,
     ModelInformationService,
     MultiselectFormControlService,
-    InstantiationTemplatesModalService
+    InstantiationTemplatesModalService,
+    LoaderService,
+    MessageModal
   ]
 })
 export class SharedModule {
index da717c8..01466f1 100644 (file)
@@ -97,6 +97,7 @@ export module Constants {
     public static SERVICE_MODEL_ID = 'serviceModelId';
     public static SERVICES_RETRY_TOPOLOGY = '../../asyncInstantiation/bulkForRetry';
     public static INSTANTIATION_TEMPLATE_TOPOLOGY = '../../instantiationTemplates/templateTopology';
+    public static PRE_LOAD = '../../preload';
     public static CONFIGURATION_PATH = '../../get_property/{name}/defaultvalue';
     public static SERVICES_JOB_AUDIT_PATH = '/auditStatus';
     public static SERVICES_PROBE_PATH = "../../probe";
index 623a4f4..aa38168 100644 (file)
@@ -27,7 +27,7 @@ export class Formasync implements OnInit {
 
   constructor(private store: NgRedux<AppState>, private _formAsyncService: FormAsyncService) { }
 
-  @ViewChild('form') form: NgForm;
+  @ViewChild('form', {static: false}) form: NgForm;
   @Input()
   set params(params: any) {
     if (params) {
index c0aeb0b..b7961ea 100644 (file)
@@ -21,7 +21,7 @@ export class NetworkSelectorComponent implements OnInit {
   @select(['service', 'networkFunctions'])
   readonly networkFunctions: Observable<any>;
 
-  @ViewChild('form') form: NgForm;
+  @ViewChild('form', {static: false}) form: NgForm;
 
   constructor(store: NgRedux<AppState>) {
     this.localStore = store;
index 87f1172..43e14e9 100644 (file)
@@ -71,11 +71,8 @@ export class VlanTaggingComponent implements OnInit {
   readonly userIdObs: Observable<any>;
 
 
-  @ViewChild(NetworkSelectorComponent)
-  public networkSelectorComponent: NetworkSelectorComponent;
-  @ViewChild(Formasync)
-  public formAsync: Formasync;
-
+  @ViewChild(NetworkSelectorComponent, {static: false}) networkSelectorComponent: NetworkSelectorComponent;
+  @ViewChild(Formasync, {static: false}) formAsync: Formasync;
 
   deploySubInterface() {
 
@@ -186,9 +183,9 @@ export class VlanTaggingComponent implements OnInit {
   isNextButtonDisabled() {
     switch (this.currentStep) {
       case WizardSteps.one:
-        return !this.formAsync.form.valid;
+        return this.formAsync ? !this.formAsync.form.valid : false;
       case WizardSteps.two:
-        return !this.networkSelectorComponent.form.valid;
+        return this.networkSelectorComponent ? !this.networkSelectorComponent.form.valid : false;
     }
   }
 
index f170f35..1d332ed 100644 (file)
@@ -239,4 +239,6 @@ sdc-checkbox {
   display: none !important;
 }
 
-
+sdc-modal {
+  z-index:  10000 !important;
+}