<%@ page language="java" contentType="text/html; charset=UTF-8" %> <%@ page import="com.hof.util.*, java.text.*, java.util.*" %> <%@ page import="java.sql.SQLException" %> <%@ page import="com.hof.content.data.ContentManagementBean" %> <%@ page import="com.hof.content.manager.ContentManagementManager" %> <%@ page import="com.hof.data.OrganisationDisplayBean" %> <%@ page import="com.hof.data.OrgReferenceCodeRltshpBean" %> <%@ page import="com.hof.data.OrgReferenceCodeDescBean" %> <%@ page import="com.hof.data.OrgReferenceCodeBean" %> <%@ page import="com.hof.data.RefCodeUtilBean" %> <%@ page import="com.hof.manager.OrgReferenceCodeDescManager" %> <%@ page import="com.hof.manager.OrgReferenceCodeManager" %> <%@ page import="com.hof.manager.OrgReferenceCodeRltshpManager" %> <%@ page import="com.hof.manager.SeqManager" %> <%@ page import="com.hof.mi.data.ReportHeaderBean" %> <%@ page import="com.hof.mi.data.ReportViewBean" %> <%@ page import="com.hof.mi.data.ReportViewSourceBean" %> <%@ page import="com.hof.mi.manager.ReportHeaderManager" %> <%@ page import="com.hof.mi.manager.ReportViewManager" %> <%@ page import="com.hof.mi.process.MIClientProcess" %> <%@ page import="com.hof.mi.util.ContentManagementCache" %> <%! static YFLogger log = YFLogger.getLogger("Fix Content Folders JSP"); /** * A little struct to hold some info about the folders that need fixing. * Folders with same name considered same for deduping. * Error type is ignored so that set algebra can be performed. */ static class Folder implements Comparable { String folderName; String subFolderName; Boolean isParentFolder; FolderError error; @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Folder other = (Folder) obj; if (folderName == null) { if (other.folderName != null) { return false; } } else if (!folderName.equals(other.folderName)) { return false; } if (subFolderName == null) { if (other.subFolderName != null) { return false; } } else if (!subFolderName.equals(other.subFolderName)) { return false; } if (isParentFolder == null) { if (other.isParentFolder != null) { return false; } } else if (!isParentFolder.equals(other.isParentFolder)) { return false; } return true; } @Override public int hashCode() { return Objects.hash(getClass(), folderName, subFolderName, isParentFolder); } @Override public int compareTo(Folder o) { if (folderName != null && !folderName.equals(o.folderName)) { if (o.folderName == null) { return 1; } return folderName.compareTo(o.folderName); } else if (subFolderName != null && !subFolderName.equals(o.subFolderName)) { if (o.subFolderName == null) { return 1; } return subFolderName.compareTo(o.subFolderName); } return -1; } } static enum FolderError { MISSING_CONTENT_MANAGEMENT("Missing folder", "Create the missing folder"), MISSING_ORG_REF_CODE("Missing OrgRefCode", "Create the missing OrgRefCode"), ORPHANED_ORG_REF_CODE("Orphaned folder", "Delete orphaned OrgRefCode"), INVALID_ENTITY_CODE("Invalid Code", "Set the ContentEntityCode to REPORT"), DRAFT_CONTENT_MANAGEMENT("Draft folder", "Set folder status to Open"); final String description; final String fix; private FolderError(String description, String fix) { this.description = description; this.fix = fix; } } /** * Find folders that are in an inconsistent state. * * 1. Folders that are in use in reports or views, but are missing from ContentManagement * 2. Folders that are present in OrgRefCodes, but missing from ContentManagement * 3. Folders that have the wrong ContentEntityCode in ContentManagement */ private static List findInconsistentFolders(DBAction db, Integer ipOrg) throws Exception { ContentManagementManager cmm = new ContentManagementManager(); OrgReferenceCodeManager orcm = new OrgReferenceCodeManager(); ReportHeaderManager rhm = new ReportHeaderManager(); ReportViewManager rvm = new ReportViewManager(); Set orphanedFolders = new HashSet(); // Retrieve everything that is currently in the DB List allContentManagements = cmm.selectContentManagements(db, ipOrg); List parentCatOrgRefs = orcm.selectOrgReferenceCodes(db, ipOrg, Const.RPTCATEGORY); List subCatOrgRefs = orcm.selectOrgReferenceCodes(db, ipOrg, Const.RPTSUBCATEGORY); Collection allReports = rhm.selectActiveReportHeaders(db, new HashSet(Arrays.asList(ipOrg)), null, false).values(); List allViews = rvm.selectAllReportViews(db, Const.UNO, ipOrg); Map contentManagementsByName = new HashMap(); for (ContentManagementBean cmb : allContentManagements) { contentManagementsByName.put(cmb.getContentTypeCode() + "::" + cmb.getContentCode(), cmb); } Map orgRefCodesByName = new HashMap(); for (RefCodeUtilBean rcub : parentCatOrgRefs) { String folderName = rcub.getValue1(); String subFolderName = "INDEX"; orgRefCodesByName.put(folderName + "::" + subFolderName, rcub); } for (RefCodeUtilBean rcub : subCatOrgRefs) { // Some folders are so broken that they do not have a parent folder String folderName = rcub.getValue4(); String subFolderName = rcub.getValue1(); orgRefCodesByName.put(folderName + "::" + subFolderName, rcub); } // Find missing folders that have open reports in them Set missingFolders = new HashSet(); Set missingOrgRefFolders = new HashSet(); for (ReportHeaderBean rhb : allReports) { if (!contentManagementsByName.containsKey(rhb.getCategoryCode() + "::" + rhb.getSubCategoryCode())) { Folder missingFolder = new Folder(); missingFolder.folderName = rhb.getCategoryCode(); missingFolder.subFolderName = rhb.getSubCategoryCode(); missingFolder.isParentFolder = false; missingFolder.error = FolderError.MISSING_CONTENT_MANAGEMENT; missingFolders.add(missingFolder); } if (!orgRefCodesByName.containsKey(rhb.getCategoryCode() + "::" + rhb.getSubCategoryCode())) { Folder missingOrgRefFolder = new Folder(); missingOrgRefFolder.folderName = rhb.getCategoryCode(); missingOrgRefFolder.subFolderName = rhb.getSubCategoryCode(); missingOrgRefFolder.isParentFolder = false; missingOrgRefFolder.error = FolderError.MISSING_ORG_REF_CODE; missingOrgRefFolders.add(missingOrgRefFolder); } } // Find missing folders that have open views in them for (ReportViewBean rvb : allViews) { if ( !UtilString.isNullOrEmpty(rvb.getContentCategoryCode()) && !UtilString.isNullOrEmpty(rvb.getContentSubCategoryCode()) && !contentManagementsByName.containsKey(rvb.getContentCategoryCode() + "::" + rvb.getContentSubCategoryCode()) ) { Folder missingFolder = new Folder(); missingFolder.folderName = rvb.getContentCategoryCode(); missingFolder.subFolderName = rvb.getContentSubCategoryCode(); missingFolder.isParentFolder = false; missingFolder.error = FolderError.MISSING_CONTENT_MANAGEMENT; missingFolders.add(missingFolder); } if ( !UtilString.isNullOrEmpty(rvb.getContentCategoryCode()) && !UtilString.isNullOrEmpty(rvb.getContentSubCategoryCode()) && !orgRefCodesByName.containsKey(rvb.getContentCategoryCode() + "::" + rvb.getContentSubCategoryCode()) ) { Folder missingOrgRefFolder = new Folder(); missingOrgRefFolder.folderName = rvb.getContentCategoryCode(); missingOrgRefFolder.subFolderName = rvb.getContentSubCategoryCode(); missingOrgRefFolder.isParentFolder = false; missingOrgRefFolder.error = FolderError.MISSING_ORG_REF_CODE; missingOrgRefFolders.add(missingOrgRefFolder); } } // For every missing subfolder, also check if the parent folder is missing too Set missingParentFolders = new HashSet(); for (Folder missingSubFolder : missingFolders) { if (!contentManagementsByName.containsKey(missingSubFolder.folderName + "::INDEX")) { Folder missingParentFolder = new Folder(); missingParentFolder.folderName = missingSubFolder.folderName; missingParentFolder.isParentFolder = true; missingParentFolder.error = FolderError.MISSING_CONTENT_MANAGEMENT; missingParentFolders.add(missingParentFolder); } } // For every subfolder that exists, check if the parent folder is missing for (ContentManagementBean cmb : allContentManagements) { if (!contentManagementsByName.containsKey(cmb.getContentTypeCode() + "::INDEX")) { Folder missingParentFolder = new Folder(); missingParentFolder.folderName = cmb.getContentTypeCode(); missingParentFolder.isParentFolder = true; missingParentFolder.error = FolderError.MISSING_CONTENT_MANAGEMENT; missingParentFolders.add(missingParentFolder); } } missingFolders.addAll(missingParentFolders); // For every missing OrgRefCode, check if the parent OrgRefCode is missing too Set missingParentOrgRefFolders = new HashSet(); for (Folder missingSubFolder : missingOrgRefFolders) { if (!orgRefCodesByName.containsKey(missingSubFolder.folderName + "::INDEX")) { Folder missingParentFolder = new Folder(); missingParentFolder.folderName = missingSubFolder.folderName; missingParentFolder.isParentFolder = true; missingParentFolder.error = FolderError.MISSING_ORG_REF_CODE; missingParentOrgRefFolders.add(missingParentFolder); } } missingOrgRefFolders.addAll(missingParentOrgRefFolders); // Find orphaned OrgRefCodes that no longer have a ContentManagement record Set orphanedOrgRefCodes = new HashSet(orgRefCodesByName.keySet()); orphanedOrgRefCodes.removeAll(contentManagementsByName.keySet()); for (String orphanedOrgRefCodeName : orphanedOrgRefCodes) { RefCodeUtilBean rcub = orgRefCodesByName.get(orphanedOrgRefCodeName); Folder orphanedFolder = new Folder(); if (parentCatOrgRefs.contains(rcub)) { orphanedFolder.isParentFolder = true; orphanedFolder.folderName = rcub.getValue1(); } else { orphanedFolder.isParentFolder = false; orphanedFolder.folderName = rcub.getValue4(); orphanedFolder.subFolderName = rcub.getValue1(); } orphanedFolder.error = FolderError.ORPHANED_ORG_REF_CODE; orphanedFolders.add(orphanedFolder); } // Orphaned folders that also have reports/views in them are not really orphaned, remove from set orphanedFolders.removeAll(missingFolders); // Find folders with invalid ContentEntityCode or Draft status Set invalidEntityFolders = new HashSet(); Set draftContentManagement = new HashSet(); for (ContentManagementBean cmb : allContentManagements) { if (!"REPORT".equals(cmb.getContentEntityCode()) && !"SIGNAL".equals(cmb.getContentEntityCode())) { Folder invalidEntityFolder = new Folder(); invalidEntityFolder.folderName = cmb.getContentTypeCode(); if ("INDEX".equals(cmb.getContentCode())) { invalidEntityFolder.isParentFolder = true; } else { invalidEntityFolder.isParentFolder = false; invalidEntityFolder.subFolderName = cmb.getContentCode(); } invalidEntityFolder.error = FolderError.INVALID_ENTITY_CODE; invalidEntityFolders.add(invalidEntityFolder); } if (!"OPEN".equals(cmb.getStatusCode())) { Folder draftFolder = new Folder(); draftFolder.folderName = cmb.getContentTypeCode(); if ("INDEX".equals(cmb.getContentCode())) { draftFolder.isParentFolder = true; } else { draftFolder.isParentFolder = false; draftFolder.subFolderName = cmb.getContentCode(); } draftFolder.error = FolderError.DRAFT_CONTENT_MANAGEMENT; draftContentManagement.add(draftFolder); } } List inconsistentFolders = new ArrayList(); inconsistentFolders.addAll(missingFolders); inconsistentFolders.addAll(missingOrgRefFolders); inconsistentFolders.addAll(orphanedFolders); inconsistentFolders.addAll(invalidEntityFolders); inconsistentFolders.addAll(draftContentManagement); Collections.sort(inconsistentFolders); return inconsistentFolders; } private static List applyFixes(DBAction db, Integer ipOrg, List inconsistentFolders) throws Exception { List fixedFolders = new ArrayList(); for (Folder inconsistentFolder : inconsistentFolders) { try { switch (inconsistentFolder.error) { case INVALID_ENTITY_CODE: fixInvalidEntityCode(db, ipOrg, inconsistentFolder); break; case MISSING_CONTENT_MANAGEMENT: fixMissingContentManagement(db, ipOrg, inconsistentFolder); break; case MISSING_ORG_REF_CODE: fixMissingOrgRefCode(db, ipOrg, inconsistentFolder); break; case ORPHANED_ORG_REF_CODE: fixOrphanedOrgRefCode(db, ipOrg, inconsistentFolder); break; case DRAFT_CONTENT_MANAGEMENT: fixDraftContentManagement(db, ipOrg, inconsistentFolder); break; } fixedFolders.add(inconsistentFolder); //Clean the caches OrgCache.getInstance().refreshRefCodeCaches(); } catch (Exception e) { log.error(e, e); } } return fixedFolders; } /** * Fix the invalid EntityCode by just setting it to the default REPORT value */ private static void fixInvalidEntityCode(DBAction db, Integer ipOrg, Folder inconsistentFolder) throws Exception { ContentManagementManager cmm = new ContentManagementManager(); String folderName = inconsistentFolder.folderName; String subFolderName = inconsistentFolder.subFolderName; if (inconsistentFolder.isParentFolder) { subFolderName = "INDEX"; } List matchingCmbs = cmm.selectContentManagements(db, ipOrg, null, folderName, subFolderName, null); if (matchingCmbs.size() != 1) { throw new IllegalStateException("More than one matching folder for " + folderName + " - " + subFolderName); } ContentManagementBean cmb = matchingCmbs.get(0); cmb.setContentEntityCode("REPORT"); cmm.updateContentManagement(db, cmb); ContentManagementCache.getInstance().remove(cmb); log.info("Reset invalid ContentEntityCode on ContentManagement with id = " + cmb.getContentManagementId()); } /** * Fix Draft Content Management by just setting it to OPEN status */ private static void fixDraftContentManagement(DBAction db, Integer ipOrg, Folder inconsistentFolder) throws Exception { ContentManagementManager cmm = new ContentManagementManager(); String folderName = inconsistentFolder.folderName; String subFolderName = inconsistentFolder.subFolderName; if (inconsistentFolder.isParentFolder) { subFolderName = "INDEX"; } List matchingCmbs = cmm.selectContentManagements(db, ipOrg, null, folderName, subFolderName, "DRAFT"); if (matchingCmbs.size() != 1) { throw new IllegalStateException("More than one matching folder for " + folderName + " - " + subFolderName); } ContentManagementBean cmb = matchingCmbs.get(0); cmb.setStatusCode("OPEN"); cmm.updateContentManagement(db, cmb); ContentManagementCache.getInstance().remove(cmb); log.info("Reset Draft status on ContentManagement with id = " + cmb.getContentManagementId()); } /** * Fix the missing content management by creating the row with some sensible defaults */ private static void fixMissingContentManagement(DBAction db, Integer ipOrg, Folder inconsistentFolder) throws Exception { ContentManagementManager cmm = new ContentManagementManager(); String folderName = inconsistentFolder.folderName; String subFolderName = inconsistentFolder.subFolderName; if (inconsistentFolder.isParentFolder) { subFolderName = "INDEX"; } ContentManagementBean cmb = new ContentManagementBean(); cmb.setContentManagementId(SeqManager.getNextObjectiveId(db)); cmb.setContentEntityCode("REPORT"); cmb.setContentTypeCode(folderName); cmb.setContentCode(subFolderName); cmb.setIpOrg(ipOrg); cmb.setLoginAccessCode("LOGIN"); cmb.setVersionHistoryRequiredFlag(false); cmb.setApprovalFlag(false); cmb.setStatusCode(Const.OPEN); cmb.setContentUUID(UUID.randomUUID().toString()); cmm.insertContentManagement(db, cmb); log.info("Inserted new ContentManagement with id = " + cmb.getContentManagementId()); } private static void fixMissingOrgRefCode(DBAction db, Integer ipOrg, Folder inconsistentFolder) throws Exception { OrgReferenceCodeManager orcm = new OrgReferenceCodeManager(); OrgReferenceCodeDescManager orcdm = new OrgReferenceCodeDescManager(); OrgReferenceCodeRltshpManager orcrm = new OrgReferenceCodeRltshpManager(); String refTypeCode; String refCode; if (inconsistentFolder.isParentFolder) { refTypeCode = Const.RPTCATEGORY; refCode = inconsistentFolder.folderName; } else { refTypeCode = Const.RPTSUBCATEGORY; refCode = inconsistentFolder.subFolderName; } OrgReferenceCodeBean orcb = new OrgReferenceCodeBean(); orcb.setIpOrg(ipOrg); orcb.setRefCode(refCode); orcb.setRefTypeCode(refTypeCode); if (orcm.selectOrgReferenceCode(db, orcb) == null) { orcb.setRefVersion("001_000"); orcm.insertOrgReferenceCode(db, orcb); log.info("Inserted OrgRefCode " + refCode); } OrgReferenceCodeDescBean orcdb = new OrgReferenceCodeDescBean(); orcdb.setIpOrg(ipOrg); orcdb.setRefCode(refCode); orcdb.setRefTypeCode(refTypeCode); if (orcdm.selectOrgReferenceCodeDesc(db, orcdb) == null) { orcdb.setRefVersion("001_000"); orcdb.setLanguageCode("EN"); orcdb.setShortDescription(refCode); orcdm.insertOrgReferenceCodeDesc(db, orcdb); log.info("Inserted OrgRefCodeDesc " + refCode); } if (!inconsistentFolder.isParentFolder) { OrgReferenceCodeRltshpBean orcrb = new OrgReferenceCodeRltshpBean(); orcrb.setIpOrg(ipOrg); orcrb.setChildRefCode(refCode); orcrb.setChildRefTypeCode(refTypeCode); if (orcrm.selectOrgReferenceCodeRltshp(db, orcrb) == null) { orcrb.setParentRefCode(inconsistentFolder.folderName); orcrb.setParentRefTypeCode(Const.RPTCATEGORY); orcrb.setRltshpTypeCode(Const.PRIMARY); orcrm.insertOrgReferenceCodeRltshp(db, orcrb); log.info("Inserted OrgRefCodeRltshp " + refCode); } } } /** * Fix orphaned OrgRefCodes by just deleting them */ private static void fixOrphanedOrgRefCode(DBAction db, Integer ipOrg, Folder inconsistentFolder) throws Exception { OrgReferenceCodeManager orcm = new OrgReferenceCodeManager(); OrgReferenceCodeDescManager orcdm = new OrgReferenceCodeDescManager(); OrgReferenceCodeRltshpManager orcrm = new OrgReferenceCodeRltshpManager(); String refTypeCode; String refCode; String logMsg; if (inconsistentFolder.isParentFolder) { refTypeCode = Const.RPTCATEGORY; refCode = inconsistentFolder.folderName; logMsg = "Deleted OrgReferenceCode for parent Content Folder " + inconsistentFolder.folderName; } else { refTypeCode = Const.RPTSUBCATEGORY; refCode = inconsistentFolder.subFolderName; logMsg = "Deleted OrgReferenceCode for Content Sub Folder " + inconsistentFolder.folderName + " - " + inconsistentFolder.subFolderName; } orcm.deleteOrgReferenceCodebyCode(db, ipOrg, refTypeCode, refCode); orcdm.deleteOrgReferenceCodeDescByCode(db, ipOrg, refTypeCode, refCode); orcrm.deleteOrgRltshps(db, ipOrg, refTypeCode, refCode); log.info(logMsg); } %> <% String action = request.getParameter("action"); String ipOrgStr = request.getParameter("ip_org"); Integer ipOrg = null; if (!UtilString.isNullOrEmpty(ipOrgStr)) { ipOrg = Integer.parseInt(ipOrgStr); } boolean orgSelected = !UtilString.isNullOrEmpty(ipOrgStr); boolean fixIt = "Fix it".equals(action); List orgList = null; List outputFolders = null; DBAction db = null; try { db = new DBAction(); orgList = MIClientProcess.loadClientOrgs(db, Const.UNO, true); if (orgSelected) { outputFolders = findInconsistentFolders(db, ipOrg); if (fixIt) { outputFolders = applyFixes(db, ipOrg, outputFolders); } } db.commit(); } catch (Exception e ) { log.error(e, e); out.write("Unexpected exception occurred: " + e); } finally { new DBActionUtil().safeDisconnect(db, log); } %>

Analyze and fix Content Folders

Client Organization

<% if (orgSelected) { %> <% if (fixIt) { %>

Fixes Applied

<% } else { %>

Inconsistent Folders

<% } %> <% if (outputFolders == null || outputFolders.isEmpty()) { %>

No inconsistencies found

<% } else { %> <% for (Folder folder : outputFolders) { out.write( "\n " + "\n " + "\n " + "\n " + "\n " + "\n " ); } %>
Folder Sub Folder Error Fix
" + folder.folderName + "" + (folder.isParentFolder ? "" : folder.subFolderName) + "" + folder.error.description + "" + folder.error.fix + "
<% if (!fixIt) { %>
<% } %> <% } %> <% } %>