diff --git a/src/main/java/org/openepics/names/rest/controller/VerificationController.java b/src/main/java/org/openepics/names/rest/controller/VerificationController.java index c698f9090779a4abd31d29cc545886580af5d7f8..5dab1f70895f2cbc92795ea2b16655711432110b 100644 --- a/src/main/java/org/openepics/names/rest/controller/VerificationController.java +++ b/src/main/java/org/openepics/names/rest/controller/VerificationController.java @@ -64,15 +64,66 @@ import io.swagger.v3.oas.annotations.Hidden; /** * This part of REST API provides verification of data migration for Naming application. * - * <p>Prerequisite(s) + * <p> + * Prerequisites. + * These are required to ensure that comparisons of content in old and migrated tables + * can be done and that result of comparisons are valid. + * <ul> + * <li>migration script run</li> + * <li>tables corresponding to both old and migrated database available</li> + * <li>must be done directly after migration has been done</li> + * <li>no changes of any kind in any way for content, either names or structures, may have been introduced</li> + * </ul> + * + * <p> + * Verification is preferably done in following order + * <ol> + * <li>structures</li> + * <li>names</li> + * <li>data is reachable</li> + * <li>comparison of old REST API vs. new REST API</li> + * </ol> + * + * <p> + * Structures. + * <ul> + * <li>Verification of structures (after) vs. name parts (before)</li> + * <li>Check that each attribute as expected in each structure entry</li> + * </ul> + * + * <p> + * Names. + * <ul> + * <li>Verification of names (after) vs. devices (before)</li> + * <li>Check that each attribute as expected in each name entry</li> + * </ul> + * + * <p> + * Data is reachable. + * <ul> + * <li>Verification of data in the sense that all data can be reached</li> + * <li>Concerns itself with new database, not old database</li> + * </ul> + * + * <p> + * Comparison of old REST API vs. new REST API. + * <ul> + * <li>Verification of differences between old REST API and new REST API</li> + * <li>Check that all content in new REST API is in old REST API and that difference is old/obsolete data</li> + * </ul> + * + * <p> + * Note * <ul> - * <li>both old and migrated database available</li> + * <li>log statements and output are technical and implementation-like, and meant to give detailed information</li> + * <li>after migration has been done and verified, this part of REST API no longer holds any function and may be removed. + * As a suggestion, this may done in the second release of the software.</li> * </ul> * * <p> * Ideally, some knowledge of database tables and object structures acquired to dig into this class. * It can be done in any case and there is documentation available. - * It is recommended to have database tables and object structures available. + * It is recommended to have database tables available in database management tool for any further queries. * * @author Lars Johansson */ @@ -86,10 +137,10 @@ public class VerificationController { // global exception handler available // // methods - // read GET /verification/migration_devicerevision - readMigrationDeviceRevision() - // read GET /verification/migration_namepartrevision - readMigrationNamePartRevision - // read GET /verification/data_reachable - readDataReachable() - // read GET /verification/restapi_oldvsnew - readRestApiOldVsNew() + // read GET /verification/migration_namepartrevision - readMigrationStructures + // read GET /verification/migration_devicerevision - readMigrationNames + // read GET /verification/data_reachable - readDataReachable + // read GET /verification/restapi_oldvsnew - readRestApiOldVsNew private static final Logger LOGGER = Logger.getLogger(VerificationController.class.getName()); @@ -124,207 +175,33 @@ public class VerificationController { } /** - * Perform verification of data migration with focus on device revision. + * Perform verification of data migration with focus on structures, i.e. name part revisions. * Ok if all entries ok and no entry nok. * * @return report of data migration */ - @GetMapping("/migration_devicerevision") - public String readMigrationDeviceRevision() { - // verification of - // name vs. devicerevision, device - // with help of namepartrevision, namepart - - // note - // check entry by entry - // ---------- - // to check 1st, 2nd, 3rd parent to determine if systemgroup, system or subsystem - // otherwise not clear how to make sure if it is supposed to be systemgroup and not system, subsystem and vice versa - // ---------- - // date may be in different format for different objects, to be formatted before being compared - // ---------- - // name.id = devicerevision.id - // name.version = devicerevision.version - // name.uuid = devicerevision.device_id (device.id --> device.uuid) - // name.namepartrevision_systemgroup_uuid = devicerevision.section_id (namepart.id --> namepart.uuid - // name.namepartrevision_system_uuid = devicerevision.section_id (namepart.id --> namepart.uuid - // name.namepartrevision_subsystem_uuid = devicerevision.section_id (namepart.id --> namepart.uuid - // name.namepartrevision_devicetype_uuid = devicerevision.devicetype_id (namepart.id --> namepart.uuid - // name.instance_index = devicerevision.instanceindex - // name.convention_name = devicerevision.conventionname - // name.convention_name_equivalence = devicerevision.conventionnameeqclass - // name.description = devicerevision.additionalinfo - // name.status = null - // name.latest = true if id = get max id for uuid (not consider status) - // name.deleted = devicerevision.deleted - // name.requested = devicerevision.requestdate - // name.requested_by = devicerevision.requestedby_id (useraccount.id --> useraccount.username) - // name.requested_comment = null - // name.processed = null - // name.processed_by = null - // name.processed_comment = devicerevision.processorcomment - - StringBuilder reportHtml = new StringBuilder(); - - // find data - // for verification - // names - // to support - // device names - // name part revisions - - List<Name> names = holderIRepositories.nameRepository().findAll(); - List<DeviceRevision> deviceNames = deviceRevisionRepository.findAll(); - List<NamePartRevision> namePartRevisions = namePartRevisionRepository.findAll(); - - prepareLogReport("readMigrationDeviceRevision, find data, names.size: " + names.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, find data, deviceNames.size: " + deviceNames.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, find data, namePartRevisions.size: " + namePartRevisions.size(), reportHtml); - - // utility - // interpret lists into hashmaps for faster retrieval in for loop below - // used to help check name entries - // ---------- - // mapIdDeviceRevision - find corresponding (old) device revision for given id - // mapUuidMaxIdName - find out latest name id for given uuid - // mapUuidNamePartRevision - find out name part revision for given uuid - - HashMap<Long, DeviceRevision> mapIdDeviceRevision = new HashMap<>((int)(deviceNames.size()/0.75 + 2)); - for (DeviceRevision deviceRevision : deviceNames) { - mapIdDeviceRevision.put(deviceRevision.getId(), deviceRevision); - } - HashMap<UUID, Long> mapUuidMaxIdName = new HashMap<>(); - for (Name name : names) { - if (mapUuidMaxIdName.get(name.getUuid()) == null - || name.getId() > mapUuidMaxIdName.get(name.getUuid())) { - mapUuidMaxIdName.put(name.getUuid(), name.getId()); - } - } - HashMap<UUID, NamePartRevision> mapUuidNamePartRevision = new HashMap<>((int)(namePartRevisions.size()/0.75 + 2)); - for (NamePartRevision namePartRevision : namePartRevisions) { - mapUuidNamePartRevision.put(namePartRevision.getNamePart().getUuid(), namePartRevision); - } - - prepareLogReport("readMigrationDeviceRevision, utility, mapIdDeviceRevision.size: " + mapIdDeviceRevision.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, utility, mapUuidMaxIdName.size: " + mapUuidMaxIdName.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, utility, mapUuidNamePartRevision.size: " + mapUuidNamePartRevision.size(), reportHtml); - - // keep track of id - // ok - // nok - SortedSet<Long> idOkDeviceRevisionDevice = new TreeSet<>(); - SortedSet<Long> idNokDeviceRevisionDevice = new TreeSet<>(); - - prepareLogReport("readMigrationDeviceRevision, check, before, idOkDeviceRevisionDevice.size: " + idOkDeviceRevisionDevice.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, check, before, idNokDeviceRevisionDevice.size: " + idNokDeviceRevisionDevice.size(), reportHtml); - - // name - // check entry by entry - // each attribute as expected - boolean check = false; - DeviceRevision deviceRevision = null; - for (Name name : names) { - deviceRevision = mapIdDeviceRevision.get(name.getId()); - - check = deviceRevision != null; - - check = check && name.getId().equals(deviceRevision.getId()); - check = check && name.getVersion().equals(deviceRevision.getVersion()); - check = check && name.getUuid().equals(deviceRevision.getDevice().getUuid()); - - // to check 1st, 2nd, 3rd parent to determine if systemgroup, system or subsystem - // otherwise not clear how to make sure if it is supposed to be systemgroup and not system, subsystem and vice versa - NamePartRevision parent1 = deviceRevision.getSection() != null - ? mapUuidNamePartRevision.get(deviceRevision.getSection().getUuid()) - : null; - NamePartRevision parent2 = parent1 != null && parent1.getParent() != null - ? mapUuidNamePartRevision.get(parent1.getParent().getUuid()) - : null; - NamePartRevision parent3 = parent2 != null && parent2.getParent() != null - ? mapUuidNamePartRevision.get(parent2.getParent().getUuid()) - : null; - // parent 1 but not parent 2, 3 - system group - // parent 1, 2 but not parent 3 - system - // parent 1, 2, 3 - subsystem - // else nok - UUID systemGroupUuid = name.getSystemGroupUuid(); - UUID systemUuid = name.getSystemUuid(); - UUID subsystemUuid = name.getSubsystemUuid(); - UUID sectionUuid = deviceRevision.getSection().getUuid(); - if (parent1 != null && parent2 == null && parent3 == null) { - check = check && sectionUuid.equals(systemGroupUuid) && systemUuid == null && subsystemUuid == null; - } else if (parent1 != null && parent2 != null && parent3 == null) { - check = check && sectionUuid.equals(systemUuid) && systemGroupUuid == null && subsystemUuid == null; - } else if (parent1 != null && parent2 != null && parent3 != null) { - check = check && sectionUuid.equals(subsystemUuid) && systemGroupUuid == null && systemUuid == null; - } else { - check = false; - } - - check = check && ((name.getDeviceTypeUuid() == null && deviceRevision.getDeviceType() == null) - || (name.getDeviceTypeUuid().equals(deviceRevision.getDeviceType().getUuid()))); - check = check && StringUtils.equals(name.getInstanceIndex(), deviceRevision.getInstanceIndex()); - check = check && StringUtils.equals(name.getConventionName(), deviceRevision.getConventionName()); - check = check && StringUtils.equals(name.getConventionNameEquivalence(), deviceRevision.getConventionNameEqClass()); - check = check && StringUtils.equals(name.getDescription(), deviceRevision.getAdditionalInfo()); - check = check && name.getStatus() == null; - - // latest - // true if id = get max id for uuid - check = check && name.isLatest() == name.getId().equals(mapUuidMaxIdName.get(name.getUuid())); - check = check && name.isDeleted() == deviceRevision.isDeleted(); - - // date may be in different format for different objects, to be formatted before being compared - check = check && ((name.getRequested() == null && deviceRevision.getRequestDate() == null) - || StringUtils.equals(SDF.format(name.getRequested()), SDF.format(deviceRevision.getRequestDate()))); - check = check && StringUtils.equals(name.getRequestedBy(), deviceRevision.getRequestedBy().getUsername()); - check = check && name.getRequestedComment() == null; - check = check && name.getProcessed() == null; - check = check && name.getProcessedBy() == null; - check = check && StringUtils.equals(name.getProcessedComment(), deviceRevision.getProcessorComment()); - - // add to count - if (check) { - idOkDeviceRevisionDevice.add(name.getId()); - } else { - idNokDeviceRevisionDevice.add(name.getId()); - } - } - - // ok if - // all entries ok - // no entry nok - boolean ok = idOkDeviceRevisionDevice.size() == names.size() - && idNokDeviceRevisionDevice.isEmpty(); - - prepareLogReport("readMigrationDeviceRevision, check, after, idOkDeviceRevisionDevice.size: " + idOkDeviceRevisionDevice.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, check, after, idNokDeviceRevisionDevice.size: " + idNokDeviceRevisionDevice.size(), reportHtml); - prepareLogReport("readMigrationDeviceRevision, ok: " + ok, reportHtml); - - return reportHtml.toString(); - } - - /** - * Perform verification of data migration with focus on name part revision. - * Ok if all entries ok and no entry nok. - * - * @return report of data migration - */ - @GetMapping("/migration_namepartrevision") - public String readMigrationNamePartRevision() { - // verification of - // systemgroup - // system - // subsystem - // discipline - // devicegroup - // devicetype - // vs. - // namepartrevision - // with help of namepartrevision, namepart - - // note + @GetMapping("/migration_structures") + public String readMigrationStructures() { + // about + // verification of structures (after) vs. name parts (before) + + // how + // find data for verification + // structures - systemgroup, system, subsystem, discipline, devicegroup, devicetype + // name parts - namepartrevision, namepart + // utility + // interpret data into hashmaps for faster retrieval in checks + // check + // for each entry in each structure + // check entry by entry + // each attribute as expected + // ok if + // all entries ok + // no entry nok + + // check // check entry by entry + // each attribute as expected // ---------- // to check parent uuid // ---------- @@ -352,15 +229,6 @@ public class VerificationController { StringBuilder reportHtml = new StringBuilder(); // find data - // for verification - // system groups - // systems - // subsystems - // disciplines - // device groups - // device types - // to support - // name part revisions List<SystemGroup> systemGroups = holderIRepositories.systemGroupRepository().findAll(); List<System> systems = holderIRepositories.systemRepository().findAll(); @@ -370,13 +238,13 @@ public class VerificationController { List<DeviceType> deviceTypes = holderIRepositories.deviceTypeRepository().findAll(); List<NamePartRevision> namePartRevisions = namePartRevisionRepository.findAll(); - prepareLogReport("readMigrationNamePartRevision, find data, systemGroups.size: " + systemGroups.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, systems.size: " + systems.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, subsystems.size: " + subsystems.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, disciplines.size: " + disciplines.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, deviceGroups.size: " + deviceGroups.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, deviceTypes.size: " + deviceTypes.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, find data, namePartRevisions.size: " + namePartRevisions.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, systemGroups.size: " + systemGroups.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, systems.size: " + systems.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, subsystems.size: " + subsystems.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, disciplines.size: " + disciplines.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, deviceGroups.size: " + deviceGroups.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, deviceTypes.size: " + deviceTypes.size(), reportHtml); + prepareLogReport("readMigrationStructures, find data, namePartRevisions.size: " + namePartRevisions.size(), reportHtml); // utility // interpret lists into hashmaps for faster retrieval in for loop below @@ -443,13 +311,13 @@ public class VerificationController { } } - prepareLogReport("readMigrationNamePartRevision, utility, mapIdNamePartRevision.size: " + mapIdNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdSystemGroup.size: " + mapUuidMaxIdSystemGroup.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdSystem.size: " + mapUuidMaxIdSystem.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdSubsystem.size: " + mapUuidMaxIdSubsystem.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdDiscipline.size: " + mapUuidMaxIdDiscipline.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdDeviceGroup.size: " + mapUuidMaxIdDeviceGroup.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, utility, mapUuidMaxIdDeviceType.size: " + mapUuidMaxIdDeviceType.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapIdNamePartRevision.size: " + mapIdNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdSystemGroup.size: " + mapUuidMaxIdSystemGroup.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdSystem.size: " + mapUuidMaxIdSystem.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdSubsystem.size: " + mapUuidMaxIdSubsystem.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdDiscipline.size: " + mapUuidMaxIdDiscipline.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdDeviceGroup.size: " + mapUuidMaxIdDeviceGroup.size(), reportHtml); + prepareLogReport("readMigrationStructures, utility, mapUuidMaxIdDeviceType.size: " + mapUuidMaxIdDeviceType.size(), reportHtml); // keep track of id // ok @@ -457,12 +325,12 @@ public class VerificationController { SortedSet<Long> idOkNamePartRevision = new TreeSet<>(); SortedSet<Long> idNokNamePartRevision = new TreeSet<>(); - prepareLogReport("readMigrationNamePartRevision, check, before, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, before, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, before, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, before, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // system group // check entry by entry - // each attribute as expected + // each attribute as expected boolean check = false; NamePartRevision namePartRevision = null; for (SystemGroup systemGroup : systemGroups) { @@ -507,12 +375,12 @@ public class VerificationController { idNokNamePartRevision.add(systemGroup.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after systemgroup, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after systemgroup, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after systemgroup, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after systemgroup, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // system // check entry by entry - // each attribute as expected + // each attribute as expected for (System system : systems) { namePartRevision = mapIdNamePartRevision.get(system.getId()); @@ -556,12 +424,12 @@ public class VerificationController { idNokNamePartRevision.add(system.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after system, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after system, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after system, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after system, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // subsystem // check entry by entry - // each attribute as expected + // each attribute as expected for (Subsystem subsystem : subsystems) { namePartRevision = mapIdNamePartRevision.get(subsystem.getId()); @@ -605,12 +473,12 @@ public class VerificationController { idNokNamePartRevision.add(subsystem.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after subsystem, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after subsystem, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after subsystem, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after subsystem, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // discipline // check entry by entry - // each attribute as expected + // each attribute as expected for (Discipline discipline : disciplines) { namePartRevision = mapIdNamePartRevision.get(discipline.getId()); @@ -653,12 +521,12 @@ public class VerificationController { idNokNamePartRevision.add(discipline.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after discipline, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after discipline, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after discipline, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after discipline, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // device group // check entry by entry - // each attribute as expected + // each attribute as expected for (DeviceGroup deviceGroup : deviceGroups) { namePartRevision = mapIdNamePartRevision.get(deviceGroup.getId()); @@ -702,12 +570,12 @@ public class VerificationController { idNokNamePartRevision.add(deviceGroup.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after devicegroup, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after devicegroup, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after devicegroup, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after devicegroup, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // device type // check entry by entry - // each attribute as expected + // each attribute as expected for (DeviceType deviceType : deviceTypes) { namePartRevision = mapIdNamePartRevision.get(deviceType.getId()); @@ -751,8 +619,8 @@ public class VerificationController { idNokNamePartRevision.add(deviceType.getId()); } } - prepareLogReport("readMigrationNamePartRevision, check, after devicetype, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after devicetype, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after devicetype, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after devicetype, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); // ok if // all entries ok @@ -760,9 +628,210 @@ public class VerificationController { boolean ok = idOkNamePartRevision.size() == namePartRevisions.size() && idNokNamePartRevision.isEmpty(); - prepareLogReport("readMigrationNamePartRevision, check, after, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, check, after, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); - prepareLogReport("readMigrationNamePartRevision, ok: " + ok, reportHtml); + prepareLogReport("readMigrationStructures, check, after, idOkNamePartRevision.size: " + idOkNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, check, after, idNokNamePartRevision.size: " + idNokNamePartRevision.size(), reportHtml); + prepareLogReport("readMigrationStructures, ok: " + ok, reportHtml); + + return reportHtml.toString(); + } + + /** + * Perform verification of data migration with focus on names, i.e. device revisions. + * Ok if all entries ok and no entry nok. + * + * @return report of data migration + */ + @GetMapping("/migration_names") + public String readMigrationNames() { + // about + // verification of names (after) vs. devices (before) + + // how + // find data for verification + // names - name + // devices - devicerevision, device + // with help of namepartrevision, namepart + // utility + // interpret data into hashmaps for faster retrieval in checks + // check + // for each name + // check entry by entry + // each attribute as expected + // ok if + // all entries ok + // no entry nok + + // check + // check entry by entry + // each attribute as expected + // ---------- + // to check 1st, 2nd, 3rd parent to determine if systemgroup, system or subsystem + // otherwise not clear how to make sure if it is supposed to be systemgroup and not system, subsystem and vice versa + // ---------- + // date may be in different format for different objects, to be formatted before being compared + // ---------- + // name.id = devicerevision.id + // name.version = devicerevision.version + // name.uuid = devicerevision.device_id (device.id --> device.uuid) + // name.namepartrevision_systemgroup_uuid = devicerevision.section_id (namepart.id --> namepart.uuid + // name.namepartrevision_system_uuid = devicerevision.section_id (namepart.id --> namepart.uuid + // name.namepartrevision_subsystem_uuid = devicerevision.section_id (namepart.id --> namepart.uuid + // name.namepartrevision_devicetype_uuid = devicerevision.devicetype_id (namepart.id --> namepart.uuid + // name.instance_index = devicerevision.instanceindex + // name.convention_name = devicerevision.conventionname + // name.convention_name_equivalence = devicerevision.conventionnameeqclass + // name.description = devicerevision.additionalinfo + // name.status = null + // name.latest = true if id = get max id for uuid (not consider status) + // name.deleted = devicerevision.deleted + // name.requested = devicerevision.requestdate + // name.requested_by = devicerevision.requestedby_id (useraccount.id --> useraccount.username) + // name.requested_comment = null + // name.processed = null + // name.processed_by = null + // name.processed_comment = devicerevision.processorcomment + + StringBuilder reportHtml = new StringBuilder(); + + // find data + + List<Name> names = holderIRepositories.nameRepository().findAll(); + List<DeviceRevision> deviceNames = deviceRevisionRepository.findAll(); + List<NamePartRevision> namePartRevisions = namePartRevisionRepository.findAll(); + + prepareLogReport("readMigrationNames, find data, names.size: " + names.size(), reportHtml); + prepareLogReport("readMigrationNames, find data, deviceNames.size: " + deviceNames.size(), reportHtml); + prepareLogReport("readMigrationNames, find data, namePartRevisions.size: " + namePartRevisions.size(), reportHtml); + + // utility + // interpret lists into hashmaps for faster retrieval in for loop below + // used to help check name entries + // ---------- + // mapIdDeviceRevision - find corresponding (old) device revision for given id + // mapUuidMaxIdName - find out latest name id for given uuid + // mapUuidNamePartRevision - find out name part revision for given uuid + + HashMap<Long, DeviceRevision> mapIdDeviceRevision = new HashMap<>((int)(deviceNames.size()/0.75 + 2)); + for (DeviceRevision deviceRevision : deviceNames) { + mapIdDeviceRevision.put(deviceRevision.getId(), deviceRevision); + } + HashMap<UUID, Long> mapUuidMaxIdName = new HashMap<>(); + for (Name name : names) { + if (mapUuidMaxIdName.get(name.getUuid()) == null + || name.getId() > mapUuidMaxIdName.get(name.getUuid())) { + mapUuidMaxIdName.put(name.getUuid(), name.getId()); + } + } + HashMap<UUID, NamePartRevision> mapUuidNamePartRevision = new HashMap<>((int)(namePartRevisions.size()/0.75 + 2)); + for (NamePartRevision namePartRevision : namePartRevisions) { + mapUuidNamePartRevision.put(namePartRevision.getNamePart().getUuid(), namePartRevision); + } + + prepareLogReport("readMigrationNames, utility, mapIdDeviceRevision.size: " + mapIdDeviceRevision.size(), reportHtml); + prepareLogReport("readMigrationNames, utility, mapUuidMaxIdName.size: " + mapUuidMaxIdName.size(), reportHtml); + prepareLogReport("readMigrationNames, utility, mapUuidNamePartRevision.size: " + mapUuidNamePartRevision.size(), reportHtml); + + // keep track of id + // ok + // nok + SortedSet<Long> idOkDeviceRevisionDevice = new TreeSet<>(); + SortedSet<Long> idNokDeviceRevisionDevice = new TreeSet<>(); + + prepareLogReport("readMigrationNames, check, before, idOkDeviceRevisionDevice.size: " + idOkDeviceRevisionDevice.size(), reportHtml); + prepareLogReport("readMigrationNames, check, before, idNokDeviceRevisionDevice.size: " + idNokDeviceRevisionDevice.size(), reportHtml); + + // name + // check entry by entry + // each attribute as expected + boolean check = false; + DeviceRevision deviceRevision = null; + try { + for (Name name : names) { + // e.g. if there has been usage of new database tables (new entries) before verification, there are more rows in those tables + // which means new and more ids than in old database tables + // which means those new ids don't exist in old database tables + // --> retrieval of device revisions for those ids will give null + + deviceRevision = mapIdDeviceRevision.get(name.getId()); + check = deviceRevision != null; + + if (check) { + check = check && name.getId().equals(deviceRevision.getId()); + check = check && name.getVersion().equals(deviceRevision.getVersion()); + check = check && name.getUuid().equals(deviceRevision.getDevice().getUuid()); + + // to check 1st, 2nd, 3rd parent to determine if systemgroup, system or subsystem + // otherwise not clear how to make sure if it is supposed to be systemgroup and not system, subsystem and vice versa + NamePartRevision parent1 = deviceRevision.getSection() != null + ? mapUuidNamePartRevision.get(deviceRevision.getSection().getUuid()) + : null; + NamePartRevision parent2 = parent1 != null && parent1.getParent() != null + ? mapUuidNamePartRevision.get(parent1.getParent().getUuid()) + : null; + NamePartRevision parent3 = parent2 != null && parent2.getParent() != null + ? mapUuidNamePartRevision.get(parent2.getParent().getUuid()) + : null; + // parent 1 but not parent 2, 3 - system group + // parent 1, 2 but not parent 3 - system + // parent 1, 2, 3 - subsystem + // else nok + UUID systemGroupUuid = name.getSystemGroupUuid(); + UUID systemUuid = name.getSystemUuid(); + UUID subsystemUuid = name.getSubsystemUuid(); + UUID sectionUuid = deviceRevision.getSection().getUuid(); + if (parent1 != null && parent2 == null && parent3 == null) { + check = check && sectionUuid.equals(systemGroupUuid) && systemUuid == null && subsystemUuid == null; + } else if (parent1 != null && parent2 != null && parent3 == null) { + check = check && sectionUuid.equals(systemUuid) && systemGroupUuid == null && subsystemUuid == null; + } else if (parent1 != null && parent2 != null && parent3 != null) { + check = check && sectionUuid.equals(subsystemUuid) && systemGroupUuid == null && systemUuid == null; + } else { + check = false; + } + + check = check && ((name.getDeviceTypeUuid() == null && deviceRevision.getDeviceType() == null) + || (name.getDeviceTypeUuid().equals(deviceRevision.getDeviceType().getUuid()))); + check = check && StringUtils.equals(name.getInstanceIndex(), deviceRevision.getInstanceIndex()); + check = check && StringUtils.equals(name.getConventionName(), deviceRevision.getConventionName()); + check = check && StringUtils.equals(name.getConventionNameEquivalence(), deviceRevision.getConventionNameEqClass()); + check = check && StringUtils.equals(name.getDescription(), deviceRevision.getAdditionalInfo()); + check = check && name.getStatus() == null; + + // latest + // true if id = get max id for uuid + check = check && name.isLatest() == name.getId().equals(mapUuidMaxIdName.get(name.getUuid())); + check = check && name.isDeleted() == deviceRevision.isDeleted(); + + // date may be in different format for different objects, to be formatted before being compared + check = check && ((name.getRequested() == null && deviceRevision.getRequestDate() == null) + || StringUtils.equals(SDF.format(name.getRequested()), SDF.format(deviceRevision.getRequestDate()))); + check = check && StringUtils.equals(name.getRequestedBy(), deviceRevision.getRequestedBy().getUsername()); + check = check && name.getRequestedComment() == null; + check = check && name.getProcessed() == null; + check = check && name.getProcessedBy() == null; + check = check && StringUtils.equals(name.getProcessedComment(), deviceRevision.getProcessorComment()); + } + + // add to count + if (check) { + idOkDeviceRevisionDevice.add(name.getId()); + } else { + idNokDeviceRevisionDevice.add(name.getId()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + // ok if + // all entries ok + // no entry nok + boolean ok = idOkDeviceRevisionDevice.size() == names.size() + && idNokDeviceRevisionDevice.isEmpty(); + + prepareLogReport("readMigrationNames, check, after, idOkDeviceRevisionDevice.size: " + idOkDeviceRevisionDevice.size(), reportHtml); + prepareLogReport("readMigrationNames, check, after, idNokDeviceRevisionDevice.size: " + idNokDeviceRevisionDevice.size(), reportHtml); + prepareLogReport("readMigrationNames, ok: " + ok, reportHtml); return reportHtml.toString(); } @@ -770,7 +839,7 @@ public class VerificationController { // ---------------------------------------------------------------------------------------------------- /** - * Perform verification of data in sense that all data can be reached. Current data is one thing but suggested data (pending) and old data (obsolete) is another thing. + * Perform verification of data in the sense that all data can be reached. Current data is one thing but suggested data (pending) and old data (obsolete) is another thing. * All data reached verification can be done like selecting all entries from tables (names, system group, system, subsystem, discipline, device group, device type) * and then take uuid and retrieve history for uuid. By that, all entries should be reached. In a sense, select distinct uuid, then retrieve history by uuid, * all ids should be encompassed by looking at all returned rows. Requires a couple of for loops and maps and sets to keep track of things. @@ -909,7 +978,7 @@ public class VerificationController { } /** - * Verify difference between old REST API and new REST API. + * Perform verification of differences between old REST API and new REST API. * * Amount is less in new than in old. Verify that all content in new REST API is in old REST API and that difference is old/obsolete data. *