Introduce Schema Set upgrade method 71/136771/8
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Tue, 5 Dec 2023 11:02:17 +0000 (11:02 +0000)
committersourabh_sourabh <sourabh.sourabh@est.tech>
Wed, 13 Dec 2023 12:53:38 +0000 (12:53 +0000)
- Incl. integration test
- Prod code is changed to use new method that update yand module.
- updated module resource to return multiple modules.

Issue-ID: CPS-1806
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
Change-Id: I751d9393ce78a3be9daeaff6d0252738c02115e0
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
16 files changed:
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy
cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/moduleResourcesResponse.json
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy

index 9b5a1fd..08f5f5b 100644 (file)
@@ -158,6 +158,7 @@ components:
           example: [ my-cm-handle1, my-cm-handle2, my-cm-handle3 ]
         moduleSetTag:
           type: string
+          default: ""
           example: 'my-module-set-tag'
 
     #Response Schemas
index 25ea3bc..750be2d 100644 (file)
@@ -38,6 +38,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
 import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
@@ -64,7 +65,7 @@ public class ModuleOperationsUtils {
     public static final String MODULE_SET_TAG_KEY = "moduleSetTag";
     public static final String MODULE_SET_TAG_MESSAGE_FORMAT = "Upgrade to ModuleSetTag: {0}";
     private static final String UPGRADE_FORMAT = "Upgrade to ModuleSetTag: %s";
-    private static final String UPGRADE_FAILED_FORMAT = UPGRADE_FORMAT + " Attempt #%d failed: %s";
+    private static final String LOCK_REASON_DETAILS_MSG_FORMAT = UPGRADE_FORMAT + " Attempt #%d failed: %s";
     private static final Pattern retryAttemptPattern = Pattern.compile("Attempt #(\\d+) failed:.+");
     private static final Pattern moduleSetTagPattern = Pattern.compile("Upgrade to ModuleSetTag: (\\S+)");
 
@@ -127,13 +128,14 @@ public class ModuleOperationsUtils {
         int attempt = 1;
         final Map<String, String> compositeStateDetails
                 = getLockedCompositeStateDetails(compositeState.getLockReason());
-        if (!compositeStateDetails.isEmpty()) {
+        if (!compositeStateDetails.isEmpty() && compositeStateDetails.containsKey(RETRY_ATTEMPT_KEY)) {
             attempt = 1 + Integer.parseInt(compositeStateDetails.get(RETRY_ATTEMPT_KEY));
         }
+        final String moduleSetTag = compositeStateDetails.get(MODULE_SET_TAG_KEY);
         compositeState.setLockReason(CompositeState.LockReason.builder()
-                .details(String.format(UPGRADE_FAILED_FORMAT,
-                        compositeStateDetails.get(MODULE_SET_TAG_KEY), attempt, errorMessage))
-                .lockReasonCategory(lockReasonCategory).build());
+                .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, StringUtils.isNotBlank(moduleSetTag)
+                        ? moduleSetTag : "not-specified", attempt, errorMessage)).lockReasonCategory(lockReasonCategory)
+                .build());
     }
 
     /**
@@ -174,13 +176,19 @@ public class ModuleOperationsUtils {
                 DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
         final CompositeState.LockReason lockReason = compositeState.getLockReason();
 
+        final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE == lockReason.getLockReasonCategory();
+        if (moduleUpgrade) {
+            log.info("Locked for module upgrade");
+            return true;
+        }
+
         final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED
                 == lockReason.getLockReasonCategory();
         final boolean failedDuringModuleUpgrade = LockReasonCategory.MODULE_UPGRADE_FAILED
                 == lockReason.getLockReasonCategory();
 
         if (failedDuringModuleSync || failedDuringModuleUpgrade) {
-            log.info("Locked for module {}.", failedDuringModuleSync ? "sync" : "upgrade");
+            log.info("Locked for module {} (last attempt failed).", failedDuringModuleSync ? "sync" : "upgrade");
             return isRetryDue(lockReason, time);
         }
         log.info("Locked for other reason");
index 841368c..a6b85a5 100644 (file)
@@ -73,34 +73,36 @@ public class ModuleSyncService {
      */
     public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
 
-        final String moduleSetTag;
         final String cmHandleId = yangModelCmHandle.getId();
         final CompositeState compositeState = yangModelCmHandle.getCompositeState();
         final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
-
-        if (inUpgrade) {
-            moduleSetTag = ModuleOperationsUtils.getLockedCompositeStateDetails(compositeState.getLockReason())
-                    .get(ModuleOperationsUtils.MODULE_SET_TAG_KEY);
-        } else {
-            moduleSetTag = yangModelCmHandle.getModuleSetTag();
-        }
+        final String moduleSetTag = getModuleSetTag(yangModelCmHandle, compositeState, inUpgrade);
 
         final Collection<ModuleReference> moduleReferencesFromCache = moduleSetTagCache.get(moduleSetTag);
 
         if (moduleReferencesFromCache == null) {
-            final Optional<DataNode> optionalExistingCmHandleWithSameModuleSetTag
+            final Optional<DataNode> existingCmHandleWithSameModuleSetTag
                     = getFirstReadyDataNodeWithModuleSetTag(moduleSetTag);
 
-            if (optionalExistingCmHandleWithSameModuleSetTag.isPresent()) {
-                final String existingCmHandleAnchorName
-                        = optionalExistingCmHandleWithSameModuleSetTag.get().getAnchorName();
-                createOrUpgradeSchemaSetUsingModuleSetTag(cmHandleId, moduleSetTag, existingCmHandleAnchorName);
+            if (existingCmHandleWithSameModuleSetTag.isPresent()) {
+                final String existingAnchorName = existingCmHandleWithSameModuleSetTag.get().getAnchorName();
+                final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
+                        upgradeOrCreateSchemaSetUsingModuleSetTag(yangModelCmHandle.getId(), moduleSetTag,
+                                existingAnchorName, inUpgrade);
+                updateModuleSetTagCache(moduleSetTag, moduleReferencesFromExistingCmHandle);
             } else {
-                syncAndCreateSchemaSet(yangModelCmHandle, moduleSetTag);
+                final Collection<ModuleReference> allModuleReferencesFromCmHandle
+                        = syncAndCreateSchemaSet(yangModelCmHandle);
+                updateModuleSetTagCache(moduleSetTag, allModuleReferencesFromCmHandle);
             }
         } else {
-            cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-                    cmHandleId, NO_NEW_MODULES, moduleReferencesFromCache);
+            if (inUpgrade) {
+                cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+                        NO_NEW_MODULES, moduleReferencesFromCache);
+            } else {
+                cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                        cmHandleId, NO_NEW_MODULES, moduleReferencesFromCache);
+            }
         }
         if (!inUpgrade) {
             cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
@@ -108,25 +110,6 @@ public class ModuleSyncService {
         setCmHandleModuleSetTag(yangModelCmHandle, moduleSetTag);
     }
 
-    private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, final String moduleSetTag) {
-        final Collection<ModuleReference> allModuleReferencesFromCmHandle =
-                dmiModelOperations.getModuleReferences(yangModelCmHandle);
-        final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
-                .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
-        final Map<String, String> newModuleNameToContentMap;
-        if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
-            newModuleNameToContentMap = NO_NEW_MODULES;
-        } else {
-            newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
-                    identifiedNewModuleReferencesFromCmHandle);
-        }
-        cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-            yangModelCmHandle.getId(), newModuleNameToContentMap, allModuleReferencesFromCmHandle);
-        if (StringUtils.isNotBlank(moduleSetTag)) {
-            moduleSetTagCache.put(moduleSetTag, allModuleReferencesFromCmHandle);
-        }
-    }
-
     /**
      * Deletes the SchemaSet for schema set id if the SchemaSet Exists.
      *
@@ -162,16 +145,56 @@ public class ModuleSyncService {
                 jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
     }
 
-    private void createOrUpgradeSchemaSetUsingModuleSetTag(final String schemaSetName,
-                                                           final String moduleSetTag,
-                                                           final String existingCmHandleAnchorName) {
+    private Collection<ModuleReference> syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle) {
+        final Collection<ModuleReference> allModuleReferencesFromCmHandle =
+                dmiModelOperations.getModuleReferences(yangModelCmHandle);
+        final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
+                .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
+        final Map<String, String> newModuleNameToContentMap;
+        if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
+            newModuleNameToContentMap = NO_NEW_MODULES;
+        } else {
+            newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
+                    identifiedNewModuleReferencesFromCmHandle);
+        }
+        cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                yangModelCmHandle.getId(), newModuleNameToContentMap, allModuleReferencesFromCmHandle);
+        return allModuleReferencesFromCmHandle;
+    }
+
+    private Collection<ModuleReference> upgradeOrCreateSchemaSetUsingModuleSetTag(final String schemaSetName,
+                                                                                  final String moduleSetTag,
+                                                                                  final String existingAnchorName,
+                                                                                  final boolean inUpgrade) {
         log.info("Found cm handle having module set tag: {}", moduleSetTag);
         final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
                 cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-                        existingCmHandleAnchorName);
-        cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-            schemaSetName, NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
-        moduleSetTagCache.put(moduleSetTag, moduleReferencesFromExistingCmHandle);
+                        existingAnchorName);
+        if (inUpgrade) {
+            cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
+                    NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
+        } else {
+            cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                    schemaSetName, NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
+        }
+        return moduleReferencesFromExistingCmHandle;
+    }
+
+    private String getModuleSetTag(final YangModelCmHandle yangModelCmHandle,
+                                   final CompositeState compositeState,
+                                   final boolean inUpgrade) {
+        if (inUpgrade) {
+            return ModuleOperationsUtils.getLockedCompositeStateDetails(compositeState.getLockReason())
+                    .get(ModuleOperationsUtils.MODULE_SET_TAG_KEY);
+        }
+        return yangModelCmHandle.getModuleSetTag();
+    }
+
+    private void updateModuleSetTagCache(final String moduleSetTag,
+                                         final Collection<ModuleReference> allModuleReferencesFromCmHandle) {
+        if (StringUtils.isNotBlank(moduleSetTag)) {
+            moduleSetTagCache.putIfAbsent(moduleSetTag, allModuleReferencesFromCmHandle);
+        }
     }
 
 }
index 896316a..e214044 100644 (file)
@@ -67,20 +67,20 @@ public class ModuleSyncTasks {
                 final YangModelCmHandle yangModelCmHandle =
                         YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode, cmHandleId);
                 final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
+                final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
                 try {
-                    moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
+                    if (!inUpgrade) {
+                        moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
+                    }
                     moduleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle);
                     yangModelCmHandle.getCompositeState().setLockReason(null);
                     cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY);
                 } catch (final Exception e) {
                     log.warn("Processing of {} module failed due to reason {}.", cmHandleId, e.getMessage());
-                    if (ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState)) {
-                        moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
-                                LockReasonCategory.MODULE_UPGRADE_FAILED, e.getMessage());
-                    } else {
-                        moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
-                                LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage());
-                    }
+                    final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED
+                            : LockReasonCategory.MODULE_SYNC_FAILED;
+                    moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
+                            lockReasonCategory, e.getMessage());
                     setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason());
                     cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
                 }
index 099fc5a..8f3d8d9 100644 (file)
@@ -108,9 +108,24 @@ class ModuleOperationsUtilsSpec extends Specification{
             assert compositeState.lockReason.lockReasonCategory == MODULE_SYNC_FAILED
             assert compositeState.lockReason.details.contains(expectedDetails)
         where:
-            scenario         | lockReason                                                                                   || expectedDetails
-            'does not exist' | null                                                                                         || 'Attempt #1 failed: new error message'
-            'exists'         | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build() || 'Attempt #3 failed: new error message'
+            scenario                           | lockReason                                                                                       || expectedDetails
+            'does not exist'                   | null                                                                                             || 'Attempt #1 failed: new error message'
+            'exists'                           | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build()     || 'Attempt #3 failed: new error message'
+    }
+
+    def 'Update lock reason details that contains #scenario'() {
+        given: 'A locked state'
+            def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.LOCKED)
+                .withLockReason(MODULE_UPGRADE, "Upgrade to ModuleSetTag: " + moduleSetTag).build()
+        when: 'update cm handle details'
+            objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, MODULE_UPGRADE_FAILED, 'new error message')
+        then: 'the composite state lock reason and details are updated'
+            assert compositeState.lockReason.lockReasonCategory == MODULE_UPGRADE_FAILED
+            assert compositeState.lockReason.details.contains("Upgrade to ModuleSetTag: " + expectedDetails)
+        where:
+            scenario               | moduleSetTag       || expectedDetails
+            'a module set tag'     | 'someModuleSetTag' || 'someModuleSetTag'
+            'empty module set tag' | ''                 || 'not-specified'
     }
 
     def 'Get all locked Cm-Handle where Lock Reason is MODULE_SYNC_FAILED cm handle #scenario'() {
index 5384f31..b68862b 100644 (file)
@@ -76,7 +76,7 @@ class ModuleSyncServiceSpec extends Specification {
         when: 'module sync is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
         then: 'create schema set from module is invoked with correct parameters'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences)
+            1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences)
         and: 'anchor is created with the correct parameters'
             1 * mockCpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1')
         where: 'the following parameters are used'
@@ -110,15 +110,17 @@ class ModuleSyncServiceSpec extends Specification {
             mockCmHandleQueries.cmHandleHasState('otherId', CmHandleState.READY) >> true
         when: 'module sync is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
-        then: 'create schema set from module is invoked for the upgraded cm handle'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
+        then: 'update schema set from module is invoked for the upgraded cm handle'
+            expectedCallsToUpgradeSchemaSet * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
+        and: 'create schema set from module is invoked for the upgraded cm handle'
+            expectedCallsToCeateSchemaSet * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
         and: 'No anchor is created for the upgraded cm handle'
             0 * mockCpsAdminService.createAnchor(*_)
         where: 'the following parameters are used'
-            scenario      | populateCache | existingCmHandlesWithSameTag
-            'new'         | false         | []
-            'in cache'    | true          | []
-            'in database' | false         | [cmHandleWithModuleSetTag]
+            scenario      | populateCache | existingCmHandlesWithSameTag || expectedCallsToUpgradeSchemaSet | expectedCallsToCeateSchemaSet
+            'new'         | false         | []                           || 0                               | 1
+            'in cache'    | true          | []                           || 1                               | 0
+            'in database' | false         | [cmHandleWithModuleSetTag]   || 1                               | 0
     }
 
     def 'upgrade model for a existing cm handle'() {
@@ -138,7 +140,7 @@ class ModuleSyncServiceSpec extends Specification {
         when: 'module upgrade is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
         then: 'the upgrade is delegated to the module service (with the correct parameters)'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences)
+            1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences)
     }
 
     def 'Delete Schema Set for CmHandle'() {
index 0d77530..b115f9a 100755 (executable)
@@ -34,6 +34,7 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -190,6 +191,21 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         schemaSetRepository.deleteByDataspaceAndNameIn(dataspaceEntity, schemaSetNames);
     }
 
+
+    @Override
+    @Transactional
+    public void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                           final Map<String, String> newModuleNameToContentMap,
+                                           final Collection<ModuleReference> allModuleReferences) {
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final SchemaSetEntity schemaSetEntity =
+            schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName);
+        storeAndLinkNewModules(newModuleNameToContentMap, schemaSetEntity);
+        updateAllModuleReferences(allModuleReferences, schemaSetEntity.getId());
+    }
+
+
+
     @Override
     @Transactional
     public void deleteUnusedYangResourceModules() {
@@ -364,4 +380,21 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         return SchemaSet.builder().name(schemaSetEntity.getName())
                 .dataspaceName(schemaSetEntity.getDataspace().getName()).build();
     }
+
+    private void storeAndLinkNewModules(final Map<String, String> newModuleNameToContentMap,
+                                        final SchemaSetEntity schemaSetEntity) {
+        final Set<YangResourceEntity> yangResourceEntities
+            = new HashSet<>(synchronizeYangResources(newModuleNameToContentMap));
+        schemaSetEntity.setYangResources(yangResourceEntities);
+        schemaSetRepository.save(schemaSetEntity);
+    }
+
+    private void updateAllModuleReferences(final Collection<ModuleReference> allModuleReferences,
+                                           final Integer schemaSetEntityId) {
+        yangResourceRepository.deleteSchemaSetYangResourceForSchemaSetId(schemaSetEntityId);
+        final List<Integer> allYangResourceIds =
+            yangResourceRepository.getResourceIdsByModuleReferences(allModuleReferences);
+        yangResourceRepository.insertSchemaSetIdYangResourceId(schemaSetEntityId, allYangResourceIds);
+    }
+
 }
index e833796..3fec462 100644 (file)
@@ -108,6 +108,10 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity
         return findAllModuleReferencesByDataspaceAndModuleNames(dataspaceName, moduleNames.toArray(new String[0]));
     }
 
+    @Modifying
+    @Query(value = "DELETE FROM schema_set_yang_resources WHERE schema_set_id = :schemaSetId", nativeQuery = true)
+    void deleteSchemaSetYangResourceForSchemaSetId(@Param("schemaSetId") int schemaSetId);
+
     @Modifying
     @Query(value = "DELETE FROM yang_resource yr WHERE NOT EXISTS "
         + "(SELECT 1 FROM schema_set_yang_resources ssyr WHERE ssyr.yang_resource_id = yr.id)", nativeQuery = true)
index 9696b28..3447a1c 100644 (file)
 package org.onap.cps.spi.impl
 
 import org.hibernate.exception.ConstraintViolationException
-import org.onap.cps.spi.CpsAdminPersistenceService
 import org.onap.cps.spi.CpsModulePersistenceService
+import org.onap.cps.spi.entities.SchemaSetEntity
 import org.onap.cps.spi.exceptions.DuplicatedYangResourceException
+import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.spi.repository.DataspaceRepository
 import org.onap.cps.spi.repository.ModuleReferenceRepository
 import org.onap.cps.spi.repository.SchemaSetRepository
 import org.onap.cps.spi.repository.YangResourceRepository
 import org.springframework.dao.DataIntegrityViolationException
 import spock.lang.Specification
-
 import java.sql.SQLException
 
 /**
@@ -39,11 +39,10 @@ class CpsModulePersistenceServiceSpec extends Specification {
 
     CpsModulePersistenceService objectUnderTest
 
-    def dataspaceRepositoryMock = Mock(DataspaceRepository)
-    def yangResourceRepositoryMock = Mock(YangResourceRepository)
-    def schemaSetRepositoryMock = Mock(SchemaSetRepository)
-    def cpsAdminPersistenceServiceMock = Mock(CpsAdminPersistenceService)
-    def moduleReferenceRepositoryMock = Mock(ModuleReferenceRepository)
+    def mockDataspaceRepository = Mock(DataspaceRepository)
+    def mockYangResourceRepository = Mock(YangResourceRepository)
+    def mockSchemaSetRepository = Mock(SchemaSetRepository)
+    def mockModuleReferenceRepository = Mock(ModuleReferenceRepository)
 
     def yangResourceName = 'my-yang-resource-name'
     def yangResourceContent = 'module stores {\n' +
@@ -68,15 +67,15 @@ class CpsModulePersistenceServiceSpec extends Specification {
     static otherIntegrityException = new DataIntegrityViolationException('another integrity exception')
 
     def setup() {
-        objectUnderTest = new CpsModulePersistenceServiceImpl(yangResourceRepositoryMock, schemaSetRepositoryMock,
-            dataspaceRepositoryMock, moduleReferenceRepositoryMock)
+        objectUnderTest = new CpsModulePersistenceServiceImpl(mockYangResourceRepository, mockSchemaSetRepository,
+            mockDataspaceRepository, mockModuleReferenceRepository)
     }
 
     def 'Store schema set error scenario: #scenario.'() {
         given: 'no yang resource are currently saved'
-            yangResourceRepositoryMock.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
+            mockYangResourceRepository.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
         and: 'persisting yang resource raises db constraint exception (in case of concurrent requests for example)'
-            yangResourceRepositoryMock.saveAll(_) >> { throw dbException }
+            mockYangResourceRepository.saveAll(_) >> { throw dbException }
         when: 'attempt to store schema set '
             def newYangResourcesNameToContentMap = [(yangResourceName):yangResourceContent]
             objectUnderTest.storeSchemaSet('my-dataspace', 'my-schema-set', newYangResourcesNameToContentMap)
@@ -90,4 +89,15 @@ class CpsModulePersistenceServiceSpec extends Specification {
             'other data failure'                | otherIntegrityException                   || DataIntegrityViolationException | 'another integrity exception'
     }
 
+    def 'Upgrade existing schema set'() {
+        given: 'old schema has empty yang resource'
+            mockYangResourceRepository.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
+        def schemaSetEntity = new SchemaSetEntity(id: 1)
+            mockSchemaSetRepository.getByDataspaceAndName(_, _) >> schemaSetEntity
+        when: 'schema set update is requested'
+            objectUnderTest.updateSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], [new ModuleReference('some module name', 'some revision name')])
+        then: 'no exception is thrown '
+            noExceptionThrown()
+    }
+
 }
index e8c3e77..2928464 100644 (file)
@@ -53,7 +53,7 @@ public interface CpsModuleService {
      * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content
      * @param allModuleReferences       All YANG resource module references
      */
-    void createOrUpgradeSchemaSetFromModules(String dataspaceName, String schemaSetName,
+    void createSchemaSetFromModules(String dataspaceName, String schemaSetName,
                                     Map<String, String> newModuleNameToContentMap,
                                     Collection<ModuleReference> allModuleReferences);
 
@@ -94,6 +94,19 @@ public interface CpsModuleService {
      */
     void deleteSchemaSetsWithCascade(String dataspaceName, Collection<String> schemaSetNames);
 
+
+    /**
+     * upgrade schema sets with existing or new modules.
+     *
+     * @param dataspaceName             dataspace name
+     * @param schemaSetName             schema set name
+     * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content
+     * @param allModuleReferences       All YANG resource module references
+     */
+    void upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                     final Map<String, String> newModuleNameToContentMap,
+                                     final Collection<ModuleReference> allModuleReferences);
+
     /**
      * Retrieve module references for the given dataspace name.
      *
index d274b51..5337237 100644 (file)
@@ -66,9 +66,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     }
 
     @Override
-    public void createOrUpgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
-        final Map<String, String> newModuleNameToContentMap,
-        final Collection<ModuleReference> allModuleReferences) {
+    public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                           final Map<String, String> newModuleNameToContentMap,
+                                           final Collection<ModuleReference> allModuleReferences) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
         cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName,
             newModuleNameToContentMap, allModuleReferences);
@@ -124,6 +124,17 @@ public class CpsModuleServiceImpl implements CpsModuleService {
         }
     }
 
+    @Override
+    public void upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                            final Map<String, String> newModuleNameToContentMap,
+                                            final Collection<ModuleReference> allModuleReferences) {
+        cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+        cpsModulePersistenceService.updateSchemaSetFromModules(dataspaceName, schemaSetName,
+                newModuleNameToContentMap, allModuleReferences);
+        yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName);
+    }
+
+
     @Override
     public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) {
         cpsValidator.validateNameCharacters(dataspaceName);
index beb3d4f..aaca2ee 100755 (executable)
@@ -43,7 +43,7 @@ public interface CpsModulePersistenceService {
     void storeSchemaSet(String dataspaceName, String schemaSetName, Map<String, String> yangResourcesNameToContentMap);
 
     /**
-     * Stores a schema set from new modules and existing modules.
+     * Stores a new schema set from new modules and existing modules.
      *
      * @param dataspaceName             Dataspace name
      * @param schemaSetName             Schema set name
@@ -53,6 +53,19 @@ public interface CpsModulePersistenceService {
     void storeSchemaSetFromModules(String dataspaceName, String schemaSetName,
         Map<String, String> newModuleNameToContentMap, Collection<ModuleReference> allModuleReferences);
 
+    /**
+     * Update an existing schema set from new modules and existing modules.
+     *
+     * @param dataspaceName             Dataspace name
+     * @param schemaSetName             Schema set name
+     * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content
+     * @param allModuleReferences       All YANG resources module references
+     */
+    void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                    final Map<String, String> newModuleNameToContentMap,
+                                    final Collection<ModuleReference> allModuleReferences);
+
+
     /**
      * Get all schema sets for a given dataspace.
      *
index 61f6741..d8edb02 100644 (file)
@@ -23,6 +23,9 @@
 
 package org.onap.cps.api.impl
 
+import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
+import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
+
 import org.onap.cps.TestUtils
 import org.onap.cps.api.CpsAdminService
 import org.onap.cps.spi.CpsModulePersistenceService
@@ -38,8 +41,6 @@ import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
-import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
-import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
 
 class CpsModuleServiceImplSpec extends Specification {
 
@@ -65,7 +66,7 @@ class CpsModuleServiceImplSpec extends Specification {
             def moduleReferenceForExistingModule = new ModuleReference('test',  '2021-10-12','test.org')
             def listOfExistingModulesModuleReference = [moduleReferenceForExistingModule]
         when: 'create schema set from modules method is invoked'
-            objectUnderTest.createOrUpgradeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
+            objectUnderTest.createSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
         then: 'processing is delegated to persistence service'
             1 * mockCpsModulePersistenceService.storeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
         and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
@@ -175,12 +176,6 @@ class CpsModuleServiceImplSpec extends Specification {
             thrown(SchemaSetInUseException)
     }
 
-    def createAnchors(int anchorCount) {
-        def anchors = []
-        (0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
-        return anchors
-    }
-
     def 'Delete multiple schema-sets when cascade is allowed.'() {
         given: '#numberOfAnchors anchors are associated with each schemaset'
             mockCpsAdminService.getAnchors('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2)
@@ -202,9 +197,16 @@ class CpsModuleServiceImplSpec extends Specification {
             numberOfAnchors << [0, 3]
     }
 
+    def 'Upgrade existing schema set'() {
+        when: 'schema set update is requested'
+        objectUnderTest.upgradeSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], moduleReferences)
+        then: 'no exception is thrown '
+        noExceptionThrown()
+    }
+
     def 'Get all yang resources module references.'() {
         given: 'an already present module reference'
-            def moduleReferences = [new ModuleReference('some module name','some revision name')]
+            def moduleReferences = getModuleReferences()
             mockCpsModulePersistenceService.getYangResourceModuleReferences('someDataspaceName') >> moduleReferences
         when: 'get yang resource module references is called'
             def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName')
@@ -228,7 +230,7 @@ class CpsModuleServiceImplSpec extends Specification {
 
     def 'Identifying new module references.'(){
         given: 'module references from cm handle'
-            def moduleReferencesToCheck = [new ModuleReference('some-module', 'some-revision')]
+            def moduleReferencesToCheck = getModuleReferences()
         when: 'identifyNewModuleReferences is called'
             objectUnderTest.identifyNewModuleReferences(moduleReferencesToCheck)
         then: 'cps module persistence service is called with module references to check'
@@ -246,4 +248,14 @@ class CpsModuleServiceImplSpec extends Specification {
         and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
             1 * mockCpsValidator.validateNameCharacters('some-dataspace-name', 'some-anchor-name')
     }
+
+    def getModuleReferences() {
+        return [new ModuleReference('some module name','some revision name')]
+    }
+
+    def createAnchors(int anchorCount) {
+        def anchors = []
+        (0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
+        return anchors
+    }
 }
index 3f9731d..5c72429 100644 (file)
@@ -84,6 +84,7 @@ public class DmiRestStubController {
         final String moduleResponseContent = ResourceFileReaderUtil
                 .getResourceFileContent(applicationContext.getResource(
                         ResourceLoader.CLASSPATH_URL_PREFIX + "module/moduleResponse.json"));
+        log.info("cm handle: {} requested for modules", cmHandle);
         return ResponseEntity.ok(moduleResponseContent);
     }
 
@@ -102,6 +103,7 @@ public class DmiRestStubController {
         final String moduleResourcesResponseContent = ResourceFileReaderUtil
                 .getResourceFileContent(applicationContext.getResource(
                         ResourceLoader.CLASSPATH_URL_PREFIX + "module/moduleResourcesResponse.json"));
+        log.info("cm handle: {} requested for module resources", cmHandle);
         return ResponseEntity.ok(moduleResourcesResponseContent);
     }
 
index 69eb9da..571c2ef 100644 (file)
@@ -7,47 +7,47 @@
        {
                "moduleName": "ietf-yang-types-2",
                "revision": "2013-07-16",
-               "yangSource": "module ietf-yang-types-2 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-2\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-2 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-2\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-16 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-3",
                "revision": "2013-07-17",
-               "yangSource": "module ietf-yang-types-3 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-3\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-3 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-3\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-17 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-4",
                "revision": "2013-07-18",
-               "yangSource": "module ietf-yang-types-4 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-4\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-4 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-4\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-18 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-5",
                "revision": "2013-07-19",
-               "yangSource": "module ietf-yang-types-5 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-5\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-5 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-5\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-19 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-6",
                "revision": "2013-07-20",
-               "yangSource": "module ietf-yang-types-6 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-6\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-6 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-6\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-20 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-7",
                "revision": "2013-07-21",
-               "yangSource": "module ietf-yang-types-7 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-7\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-7 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-7\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-21 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-8",
                "revision": "2013-07-22",
-               "yangSource": "module ietf-yang-types-8 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-8\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-8 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-8\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-22 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-9",
                "revision": "2013-07-23",
-               "yangSource": "module ietf-yang-types-9 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-9\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-9 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-9\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-23 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-10",
                "revision": "2013-07-24",
-               "yangSource": "module ietf-yang-types-10 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-10\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-10 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-10\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-24 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        }
 ]
 
index d33a774..2e1b082 100644 (file)
@@ -52,6 +52,7 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
 
     def newYangResourcesNameToContentMap = [:]
     def moduleReferences = []
+    def noNewModules = [:]
 
     def setup() {
         objectUnderTest = cpsModuleService
@@ -94,7 +95,7 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
             moduleReferences.addAll(existingModuleReferences)
         when: 'the new schema set is created'
             def schemaSetName = "NewSchemaWith${numberOfNewModules}Modules"
-            objectUnderTest.createOrUpgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
         and: 'associated with a new anchor'
             cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor')
         then: 'the new anchor has the correct number of modules'
@@ -261,16 +262,75 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
             'schema set does not exists' | FUNCTIONAL_TEST_DATASPACE_1 | 'unknown'       || SchemaSetNotFoundException
     }
 
+    /*
+        U P G R A D E
+     */
+
+    def 'Upgrade schema set (with existing and new modules, no matching module set tag in NCMP)'() {
+        given: 'an anchor and schema set with 2 modules (to be upgraded)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('original', 2)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, [])
+            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor')
+            def yangResourceModuleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert yangResourceModuleReferencesBeforeUpgrade.size() == 2
+            assert yangResourceModuleReferencesBeforeUpgrade.containsAll([new ModuleReference('original_0','2000-01-01'),new ModuleReference('original_1','2001-01-01')])
+        and: 'two new 2 modules (from node)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('new', 2)
+            def newModuleReferences = [new ModuleReference('new_0','2000-01-01'),new ModuleReference('new_1','2001-01-01')]
+        and: 'a list of all module references (normally retrieved from node)'
+            def allModuleReferences = []
+            allModuleReferences.add(existingModuleReference)
+            allModuleReferences.addAll(newModuleReferences)
+        when: 'the schema set is upgraded'
+            objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, allModuleReferences)
+        then: 'the new anchor has the correct new and existing modules'
+            def yangResourceModuleReferencesAfterUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert yangResourceModuleReferencesAfterUpgrade.size() == 3
+            assert yangResourceModuleReferencesAfterUpgrade.contains(existingModuleReference)
+            assert yangResourceModuleReferencesAfterUpgrade.containsAll(newModuleReferences);
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['targetSchema'])
+    }
+    
+    def 'Upgrade existing schema set from another anchor (used in NCMP for matching module set tag)'() {
+        given: 'an anchor and schema set with 1 module (target)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('target', 1)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, [])
+            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor')
+            def moduleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert moduleReferencesBeforeUpgrade.size() == 1
+        and: 'another anchor and schema set with 2 other modules (source for upgrade)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('source', 2)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', newYangResourcesNameToContentMap, [])
+            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', 'sourceAnchor')
+            assert objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor').size() == 2
+        when: 'the target schema is upgraded using the module references from the source anchor'
+            def moduleReferencesFromSourceAnchor = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor')
+            objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', noNewModules, moduleReferencesFromSourceAnchor)
+        then: 'the target schema now refers to the source modules (with namespace) modules'
+            def schemaSetModuleReferencesAfterUpgrade = getObjectUnderTest().getSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema').moduleReferences
+            assert schemaSetModuleReferencesAfterUpgrade.containsAll([new ModuleReference('source_0','2000-01-01','org:onap:ccsdk:sample'),new ModuleReference('source_1','2001-01-01','org:onap:ccsdk:sample')]);
+        and: 'the associated target anchor has the same module references (without namespace but that is a legacy issue)'
+            def anchorModuleReferencesAfterUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert anchorModuleReferencesAfterUpgrade.containsAll([new ModuleReference('source_0','2000-01-01'),new ModuleReference('source_1','2001-01-01')]);
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['sourceSchema', 'targetSchema'])
+    }
+
     /*
         H E L P E R   M E T H O D S
      */
 
     def populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfModules) {
+        populateNewYangResourcesNameToContentMapAndAllModuleReferences('name', numberOfModules)
+    }
+
+    def populateNewYangResourcesNameToContentMapAndAllModuleReferences(namePrefix, numberOfModules) {
         numberOfModules.times {
-            def uniqueName = 'name_' + it
+            def uniqueName = namePrefix + '_' + it
             def uniqueRevision = String.valueOf(2000 + it) + '-01-01'
             moduleReferences.add(new ModuleReference(uniqueName, uniqueRevision))
-            def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision)
+            def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision).replace('module test_module', 'module '+uniqueName)
             newYangResourcesNameToContentMap.put(uniqueRevision, uniqueContent)
         }
     }