/// <summary>
        /// Helper function that runs all of those checks that operate on each user group;
        /// intended to make the checks slightly more efficient by running them all at once
        /// rather than looping through all of the elements multiple times
        /// </summary>
        /// <param name="msgs">Add any GP messages to this object</param>
        /// <param name="errorCount">Counter used to track the number of problems found</param>
        /// <param name="logFileWriter">Object used to write error descriptions to a text file</param>
        private void ExecuteGroupChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter)
        {
            // Check for groups w/o privileges
            if (!m_flagGroupsWithoutPrivileges &&
                !m_flagGroupsWithoutEmails &&
                !m_flagGroupsWithoutUsers)
            {
                return;
            }

            IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;

            // Put the items into a sorted list in order to make the output easier to
            // read/follow
            IJTXUserGroupSet allGroups = configMgr.UserGroups;
            SortedList <string, IJTXUserGroup2> allGroupsSorted = new SortedList <string, IJTXUserGroup2>();

            for (int i = 0; i < allGroups.Count; i++)
            {
                allGroupsSorted[allGroups.get_Item(i).Name] = allGroups.get_Item(i) as IJTXUserGroup2;
            }

            // Iterate over each group, performing the specified checks
            foreach (IJTXUserGroup2 group in allGroupsSorted.Values)
            {
                if (m_flagGroupsWithoutPrivileges)
                {
                    if (group.Privileges.Count < 1)
                    {
                        string message = "Group '" + group.Name + "' has no associated privileges";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagGroupsWithoutEmails)
                {
                    if (group.Email == null || group.Email.Equals(string.Empty))
                    {
                        string message = "Group '" + group.Name + "' has no associated e-mail address";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagGroupsWithoutUsers)
                {
                    if (group.Users.Count <= 0)
                    {
                        string message = "Group '" + group.Name + "' has no users assigned to it";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }
            }
        }
        /// <summary>
        /// Helper function that runs all of those checks that operate on each user in
        /// the database; intended to make the checks slightly more efficient by running
        /// through them all at once rather than looping through all of the elements
        /// multiple times
        /// </summary>
        /// <param name="msgs">Add any GP messages to this object</param>
        /// <param name="errorCount">Counter used to track the number of problems found</param>
        /// <param name="logFileWriter">Object used to write error descriptions to a text file</param>
        private void ExecuteUserChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter)
        {
            // Only continue executing this function if needed
            if (!m_flagUsersWithoutEmails &&
                !m_flagUsersWithoutGroups)
            {
                return;
            }

            IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;

            // Put the items into a sorted list in order to make the output easier to
            // read/follow
            IJTXUserSet allUsers = configMgr.Users;
            SortedList <string, IJTXUser3> allUsersSorted = new SortedList <string, IJTXUser3>();

            for (int i = 0; i < allUsers.Count; i++)
            {
                allUsersSorted[allUsers.get_Item(i).UserName] = allUsers.get_Item(i) as IJTXUser3;
            }

            // Iterate through each item
            foreach (IJTXUser3 user in allUsersSorted.Values)
            {
                if (m_flagUsersWithoutEmails)
                {
                    if (user.Email == null || user.Email.Equals(string.Empty))
                    {
                        string message = "User '" + user.UserName + "' (" + user.FullName +
                                         ") does not have an e-mail address configured";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagUsersWithoutGroups)
                {
                    if (user.Groups.Count < 1)
                    {
                        string message = "User '" + user.UserName + "' (" + user.FullName +
                                         ") does not belong to any groups";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }
            }
        }
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);

            try
            {
                // Ensure that the current user has admin access to the current Workflow Manager DB
                if (!CurrentUserIsWmxAdministrator())
                {
                    throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR);
                }

                // Stash away the executing user's information, if appropriate
                string             username      = ESRI.ArcGIS.JTXUI.ConfigurationCache.GetCurrentSystemUser(ESRI.ArcGIS.JTXUI.ConfigurationCache.UseUserDomain);
                IJTXConfiguration3 configMgr     = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
                IJTXUser3          executingUser = configMgr.GetUser(username) as IJTXUser3;

                // Import the AD information
                string domain         = System.Environment.UserDomainName;
                string domainUsername = string.Empty;
                string domainPassword = string.Empty;
                int    numUsers       = 0;
                int    numGroups      = 0;
                ActiveDirectoryHelper.SyncronizeJTXDatabaseWithActiveDirectory(this.WmxDatabase, domain, domainUsername, domainPassword, m_userGroup, m_groupGroup, out numGroups, out numUsers);

                // If the tool was set to preserve the current user's account and the user
                // was removed from the DB, then re-add their account
                if (configMgr.GetUser(username) == null)
                {
                    if (m_preserveCurrentUser)
                    {
                        IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2;
                        IJTXUserConfig         newUser    = configEdit.CreateUser() as IJTXUserConfig;
                        newUser.FirstName_2 = executingUser.FirstName;
                        newUser.FullName_2  = executingUser.FullName;
                        newUser.LastName_2  = executingUser.LastName;
                        newUser.UserName_2  = executingUser.UserName;
                        (newUser as IJTXUser3).IsAdministrator = executingUser.IsAdministrator;
                        newUser.Store();

                        msgs.AddMessage("User '" + username + "' not found in Active Directory group '" + m_userGroup + "'; re-added placeholder to Workflow Manager database");
                    }
                    else
                    {
                        msgs.AddWarning("User '" + username + "' removed from Workflow Manager database");
                    }
                }

                // Update the output parameters
                WmauParameterMap  paramMap = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_NUM_USERS);
                IGPLong           value    = new GPLongClass();
                value.Value    = numUsers;
                outParam.Value = value as IGPValue;

                outParam       = paramMap.GetParamEdit(C_PARAM_OUT_NUM_GROUPS);
                value          = new GPLongClass();
                value.Value    = numGroups;
                outParam.Value = value as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                try
                {
                    WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                    msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            finally
            {
                // Release any COM objects here!
            }
        }
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);

            // Set the default properties for the specified job type
            try
            {
                IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
                IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2;
                IJTXJobTypeEdit3       jobType    = configEdit.GetJobType(m_jobTypeName) as IJTXJobTypeEdit3;

                // Set the default data workspace for the selected job type
                if (m_dataWorkspaceName.Equals(C_OPT_NONE))
                {
                    jobType.DefaultDataWorkspace = null;
                    msgs.AddMessage("Clearing default data workspace for job type '" + m_jobTypeName + "'");
                }
                else
                {
                    // Translate the workspace name to a DB name object
                    IJTXDataWorkspaceName dwName =
                        Common.WmauHelperFunctions.LookupWorkspaceNameObj(this.WmxDatabase, m_dataWorkspaceName);

                    msgs.AddMessage("Default data workspace for job type '" + m_jobTypeName + "' is now '" + dwName.Name + "'");
                    jobType.DefaultDataWorkspace = dwName;
                }

                // Set the default parent version for the selected job type
                if (m_parentVersion.Equals(C_OPT_NONE))
                {
                    msgs.AddMessage("Clearing default parent version for job type '" + m_jobTypeName + "'");
                    jobType.DefaultParentVersionName_2 = string.Empty;
                }
                else
                {
                    msgs.AddMessage("Default parent version for job type '" + m_jobTypeName + "' is now '" + m_parentVersion + "'");
                    jobType.DefaultParentVersionName_2 = m_parentVersion;
                }

                // Save the changes to the job type
                jobType.Store();

                // Set the output parameter
                WmauParameterMap  paramMap     = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_OUT_DATA_WORKSPACE);
                IGPString         outValue     = new GPStringClass();
                outValue.Value     = m_jobTypeName;
                outParamEdit.Value = outValue as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
            }
        }
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);

            try
            {
                // Ensure that the current user has admin access to the current Workflow Manager DB
                if (!CurrentUserIsWmxAdministrator())
                {
                    throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR);
                }

                // Indicate if changes are not actually being made
                string actionStr = "  Deleting";
                if (m_previewChanges)
                {
                    msgs.AddMessage("PREVIEWING CHANGES ONLY; no changes will be made");
                    actionStr = "  Found";
                }

                IJTXConfiguration3     configMgr  = WmxDatabase.ConfigurationManager as IJTXConfiguration3;
                IJTXConfigurationEdit2 configEdit = WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2;

                // Find all of the orphans in the database
                msgs.AddMessage("Searching for orphaned items...");
                int orphanCount = UpdateAllOrphans();
                msgs.AddMessage("Found " + orphanCount.ToString() + " total orphaned items");

                // If requested, delete any workflows first
                if (m_cleanWorkflows)
                {
                    List <int> unusedWorkflowIds = m_unusedWorkflows.Keys.ToList();
                    unusedWorkflowIds.Sort();
                    foreach (int id in unusedWorkflowIds)
                    {
                        msgs.AddMessage(actionStr + " workflow " + id.ToString() + " (" + m_unusedWorkflows[id] + ")");
                        if (!this.m_previewChanges)
                        {
                            configMgr.DeleteWorkflow(id);
                        }
                    }
                }

                // If requested, delete any step types
                if (m_cleanStepTypes)
                {
                    List <int> unusedStepTypeIds = m_unusedStepTypes.Keys.ToList();
                    unusedStepTypeIds.Sort();
                    foreach (int stepTypeId in unusedStepTypeIds)
                    {
                        msgs.AddMessage(actionStr + " step type " + stepTypeId.ToString() + " (" + m_unusedStepTypes[stepTypeId] + ")");
                        if (!this.m_previewChanges)
                        {
                            configEdit.DeleteStepType(stepTypeId);
                        }
                    }
                }

                // If requested, delete any status types
                if (m_cleanStatusTypes)
                {
                    List <int> unusedStatusTypeIds = m_unusedStatusTypes.Keys.ToList();
                    unusedStatusTypeIds.Sort();
                    foreach (int statusTypeId in unusedStatusTypeIds)
                    {
                        msgs.AddMessage(actionStr + " status type " + statusTypeId.ToString() + " (" + m_unusedStatusTypes[statusTypeId] + ")");
                        if (!this.m_previewChanges)
                        {
                            configEdit.DeleteStatus(statusTypeId);
                        }
                    }
                }

                // If requested, delete any priority types
                if (m_cleanPriorities)
                {
                    List <int> unusedPriorityTypeIds = m_unusedPriorities.Keys.ToList();
                    unusedPriorityTypeIds.Sort();
                    foreach (int priority in unusedPriorityTypeIds)
                    {
                        msgs.AddMessage(actionStr + " priority " + priority.ToString() + " (" + m_unusedPriorities[priority] + ")");
                        if (!m_previewChanges)
                        {
                            configEdit.DeletePriority(priority);
                        }
                    }
                }

                // If requested, delete any unused Task Assistant workbooks
                if (m_cleanTaWorkbooks)
                {
                    List <string> unusedTaWorkbookNames = m_unusedTaWorkbooks.Keys.ToList();
                    unusedTaWorkbookNames.Sort();
                    foreach (string workbookName in unusedTaWorkbookNames)
                    {
                        msgs.AddMessage(actionStr + " workbook " + workbookName);
                        if (!m_previewChanges)
                        {
                            configMgr.RemoveTaskAssistantWorkflowRecord(workbookName);
                        }
                    }
                }

                // If requested, delete any unused users
                if (m_cleanUsers)
                {
                    List <string> unusedUserNames = m_unusedUsers.Keys.ToList();
                    unusedUserNames.Sort();
                    foreach (string user in unusedUserNames)
                    {
                        msgs.AddMessage(actionStr + " user " + user + " (" + m_unusedUsers[user] + ")");
                        if (!m_previewChanges)
                        {
                            configEdit.DeleteUser(user);
                        }
                    }
                }

                // If requested, delete any unused map documents
                if (m_cleanMapDocs)
                {
                    List <string> unusedMapDocs = m_unusedMapDocs.Keys.ToList();
                    unusedMapDocs.Sort();
                    foreach (string mapName in unusedMapDocs)
                    {
                        msgs.AddMessage(actionStr + " map document " + mapName + " (" + m_unusedMapDocs[mapName].ToString() + ")");
                        if (!m_previewChanges)
                        {
                            configMgr.DeleteJTXMap(m_unusedMapDocs[mapName]);
                        }
                    }
                }

                // Set the output parameter
                WmauParameterMap  paramMap     = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_NUM_ITEMS_DELETED);
                IGPLong           outValue     = new GPLongClass();
                outValue.Value     = orphanCount;
                outParamEdit.Value = outValue as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                try
                {
                    WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                    msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
        }
        /// <summary>
        /// Find those map documents embedded in the database that are not being
        /// referenced in any way
        /// </summary>
        /// <returns>The total number of orphaned items found</returns>
        private int UpdateOrphanedMapDocuments()
        {
            SortedList <string, int> unusedItems = new SortedList <string, int>();
            IJTXDatabase3            wmxDb       = this.WmxDatabase;
            IJTXConfiguration3       configMgr   = wmxDb.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2   configEdit  = wmxDb.ConfigurationManager as IJTXConfigurationEdit2;

            IJTXMapSet allMaps = configMgr.JTXMaps;
            Dictionary <string, int> allMapNames = new Dictionary <string, int>();

            for (int i = 0; i < allMaps.Count; i++)
            {
                IJTXMap map = allMaps.get_Item(i);
                allMapNames[map.Name] = map.ID;
            }

            Dictionary <string, int> usedItems = new Dictionary <string, int>();

            // Find the map types that are associated with job types
            IJTXJobTypeSet allJobTypes = configMgr.JobTypes;

            for (int i = 0; i < allJobTypes.Count; i++)
            {
                // TODO: Skip orphaned job types

                IJTXJobType3 jobType = allJobTypes.get_Item(i) as IJTXJobType3;
                if (jobType.AOIMap != null)
                {
                    usedItems[jobType.AOIMap.Name] = jobType.AOIMap.ID;
                }
                if (jobType.JobMap != null)
                {
                    usedItems[jobType.JobMap.Name] = jobType.JobMap.ID;
                }
            }

            // If necessary, find the map types launched by custom steps.  Look for
            // the "/mxd:" argument as an identifier.
            IJTXStepTypeSet allStepTypes = wmxDb.ConfigurationManager.StepTypes;

            for (int i = 0; i < allStepTypes.Count; i++)
            {
                IJTXStepType2 stepType = allStepTypes.get_Item(i) as IJTXStepType2;

                // Skip orphaned step types
                if (m_unusedStepTypes.Keys.Contains(stepType.ID))
                {
                    continue;
                }

                for (int j = 0; j < stepType.Arguments.Length; j++)
                {
                    string stepArg = stepType.Arguments[j].ToString();
                    if (stepArg.StartsWith(C_MAP_DOC_FLAG))
                    {
                        string suffix = stepArg.Substring(C_MAP_DOC_FLAG.Length);
                        suffix = suffix.Trim(new char[] { '"' });
                        if (allMapNames.Keys.Contains(suffix))
                        {
                            usedItems[suffix] = allMapNames[suffix];
                        }
                    }
                }
            }

            // Add in the map document that's used as the template map document
            // (if one exists)
            IJTXConfigurationProperties configProps = this.WmxDatabase.ConfigurationManager as IJTXConfigurationProperties;
            string mapIdStr = configProps.GetProperty(Constants.JTX_PROPERTY_MAPVIEW_MAP_GUID);

            if (mapIdStr != null && !mapIdStr.Equals(string.Empty))
            {
                for (int i = 0; i < allMaps.Count; i++)
                {
                    IJTXMap        tempMap   = allMaps.get_Item(i);
                    IJTXIdentifier tempMapId = tempMap as IJTXIdentifier;
                    if (tempMapId.GUID.Equals(mapIdStr))
                    {
                        usedItems[tempMap.Name] = tempMap.ID;
                        break;
                    }
                }
            }

            // Loop over all the map documents in the DB, looking for anything
            // that we didn't identify as "in use"
            foreach (string name in allMapNames.Keys)
            {
                if (!usedItems.ContainsKey(name))
                {
                    m_unusedMapDocs[name] = allMapNames[name];
                }
            }

            return(m_unusedMapDocs.Count);
        }
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);

            try
            {
                // Ensure that the current user has admin access to the current Workflow Manager DB
                if (!CurrentUserIsWmxAdministrator())
                {
                    throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR);
                }

                IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2;

                // Look up the appropriate privilege(s) and group(s)
                IJTXPrivilegeSet privileges = null;
                if (m_privilegeName.Equals(C_OPT_ALL_PRIVILEGES))
                {
                    privileges = configEdit.Privileges;
                }
                else
                {
                    privileges = new JTXPrivilegeSetClass();
                    (privileges as IJTXPrivilegeSetEdit).Add(configEdit.GetPrivilege(m_privilegeName));
                }

                IJTXUserGroupSet groups = null;
                if (m_groupName.Equals(C_OPT_ALL_GROUPS))
                {
                    groups = configEdit.UserGroups;
                }
                else
                {
                    groups = new JTXUserGroupSetClass();
                    (groups as IJTXUserGroupSetEdit).Add(configEdit.GetUserGroup(m_groupName));
                }

                // Add/remove the privilege(s) to the group(s)
                for (int i = 0; i < privileges.Count; i++)
                {
                    IJTXPrivilege2 privilege = privileges.get_Item(i) as IJTXPrivilege2;
                    for (int j = 0; j < groups.Count; j++)
                    {
                        IJTXUserGroupConfig2 targetGroup = groups.get_Item(j) as IJTXUserGroupConfig2;
                        if (m_privilegeAction.Equals(C_OPT_GRANT))
                        {
                            targetGroup.AssignPrivilegeToGroup2(privilege.UID);
                        }
                        else
                        {
                            targetGroup.RemovePrivilegeFromGroup2(privilege.UID);
                        }
                        targetGroup.Store();
                    }
                }

                // Update the output parameter
                WmauParameterMap  paramMap = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_PRIVILEGE_NAME);
                IGPString         strValue = new GPStringClass();
                strValue.Value = m_privilegeName;
                outParam.Value = strValue as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                try
                {
                    WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                    msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            finally
            {
                // Release any COM objects here!
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);

            try
            {
                // Ensure that the current user has admin access to the current Workflow Manager DB
                if (!CurrentUserIsWmxAdministrator())
                {
                    throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR);
                }

                IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2;

                // Look up the appropriate user(s)
                IJTXUserSet users = null;
                if (m_userName.Equals(C_OPT_ALL_USERS))
                {
                    users = configEdit.Users;
                }
                else
                {
                    users = new JTXUserSetClass();
                    (users as IJTXUserSetEdit).Add(configEdit.GetUser(m_userName));
                }

                // Grant/revoke admin access to the specified users
                for (int i = 0; i < users.Count; i++)
                {
                    IJTXUser3 user = users.get_Item(i) as IJTXUser3;
                    user.IsAdministrator = m_privilegeAction.Equals(C_OPT_GRANT) ? true : false;
                    (user as IJTXUserConfig).Store();
                }

                // If the tool was set to preserve the current user's access and the tool removed it,
                // re-grant their access
                string    username = ESRI.ArcGIS.JTXUI.ConfigurationCache.GetCurrentSystemUser(ESRI.ArcGIS.JTXUI.ConfigurationCache.UseUserDomain);
                IJTXUser3 userObj  = configEdit.GetUser(username) as IJTXUser3;
                if (!userObj.IsAdministrator)
                {
                    if (m_preserveCurrentUser)
                    {
                        userObj.IsAdministrator = true;
                        (userObj as IJTXUserConfig).Store();
                        msgs.AddMessage("Re-granting admin access for user '" + username + "'");
                    }
                    else
                    {
                        msgs.AddWarning("User '" + username + "' is no longer an administrator on this Workflow Manager database");
                    }
                }

                // Update the output parameter
                WmauParameterMap  paramMap = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_USER_NAME);
                IGPString         strValue = new GPStringClass();
                strValue.Value = m_userName;
                outParam.Value = strValue as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                try
                {
                    WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                    msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            finally
            {
                // Release any COM objects here!
            }
        }
        /// <summary>
        /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed.
        /// </summary>
        /// <param name="paramValues"></param>
        /// <param name="trackCancel"></param>
        /// <param name="envMgr"></param>
        /// <param name="msgs"></param>
        public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs)
        {
            // Do some common error-checking
            base.Execute(paramValues, trackCancel, envMgr, msgs);
            StreamWriter logFileWriter = null;

            try
            {
                int errorCount = 0;

                if (!string.IsNullOrEmpty(m_logFilePath))
                {
                    logFileWriter = new StreamWriter(m_logFilePath);
                }

                IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
                IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;
                IJTXJobManager         jobMgr     = this.WmxDatabase.JobManager;

                // Workflow Manager intentionally caches the data workspaces in the system.  To ensure
                // that we have the most current list of data workspaces, invalidate this cache
                // before attempting to retrieve the list from the system.
                this.WmxDatabase.InvalidateDataWorkspaceNames();

                // Run checks against users
                ExecuteUserChecks(msgs, ref errorCount, logFileWriter);

                // Run checks against groups
                ExecuteGroupChecks(msgs, ref errorCount, logFileWriter);

                // Run checks against any existing jobs
                ExecuteJobChecks(msgs, ref errorCount, logFileWriter);

                // Check for any template job types with an invalid default assignment
                ExecuteJobTypeChecks(msgs, ref errorCount, logFileWriter);

                // Check the workflow steps for problems
                ExecuteWorkflowStepChecks(msgs, ref errorCount, logFileWriter);

                // Set the output parameter
                WmauParameterMap  paramMap     = new WmauParameterMap(paramValues);
                IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_OUT_ISSUES_FOUND);
                IGPLong           outValue     = new GPLongClass();
                outValue.Value     = errorCount;
                outParamEdit.Value = outValue as IGPValue;

                msgs.AddMessage(Properties.Resources.MSG_DONE);
            }
            catch (WmauException wmEx)
            {
                try
                {
                    msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            catch (Exception ex)
            {
                try
                {
                    WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR);
                    msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message);
                }
                catch
                {
                    // Catch anything else that possibly happens
                }
            }
            finally
            {
                // Release any COM objects here!
                if (logFileWriter != null)
                {
                    logFileWriter.Close();
                }
            }
        }
        /// <summary>
        /// Helper function that runs all of those checks that operate on each step in
        /// every workflow; intended to make the checks slightly more efficient by running
        /// through them all at once rather than looping through all of the elements
        /// multiple times
        /// </summary>
        /// <param name="msgs">Add any GP messages to this object</param>
        /// <param name="errorCount">Counter used to track the number of problems found</param>
        /// <param name="logFileWriter">Object used to write error descriptions to a text file</param>
        private void ExecuteWorkflowStepChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter)
        {
            // Only continue executing this function if needed
            if (!m_flagInvalidStepAssign &&
                !m_flagUnassignedSteps &&
                !m_flagZeroPctSteps &&
                !m_flagDifferingStepNames)
            {
                return;
            }

            IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;

            // Put the items into a sorted list in order to make the output easier to
            // read/follow
            IJTXWorkflowSet allWorkflows = configMgr.Workflows;
            SortedList <string, IJTXWorkflow> allWorkflowsSorted = new SortedList <string, IJTXWorkflow>();

            for (int i = 0; i < allWorkflows.Count; i++)
            {
                allWorkflowsSorted[allWorkflows.get_Item(i).Name] = allWorkflows.get_Item(i);
            }

            // Iterate through each item
            foreach (IJTXWorkflow workflow in allWorkflowsSorted.Values)
            {
                IJTXWorkflowConfiguration workflowCfg = workflow as IJTXWorkflowConfiguration;
                int[] allStepIds = workflowCfg.GetAllSteps();
                foreach (int j in allStepIds)
                {
                    IJTXStep3 step       = workflowCfg.GetStep(j) as IJTXStep3;
                    string    assignedTo = step.AssignedTo;

                    // Check for any default step types with an invalid step assignment
                    if (m_flagInvalidStepAssign)
                    {
                        if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null)
                        {
                            string message = "Workflow '" + workflow.Name + "', step '" +
                                             step.StepName + "' assigned to unknown user '" + assignedTo + "'";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                        else if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null)
                        {
                            string message = "Workflow '" + workflow.Name + "', step '" +
                                             step.StepName + "' assigned to unknown group '" + assignedTo + "'";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                    }

                    // Check for any steps that have not been assigned to a group or user
                    if (m_flagUnassignedSteps)
                    {
                        if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeUnassigned)
                        {
                            string message = "Workflow '" + workflow.Name + "', step '" +
                                             step.StepName + "' is unassigned";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                    }

                    // Check for any steps whose "post-complete" percentage is 0
                    if (m_flagZeroPctSteps)
                    {
                        if (step.DefaultPercComplete < double.Epsilon)
                        {
                            string message = "Workflow '" + workflow.Name + "', step '" +
                                             step.StepName + "' sets percent complete to 0";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                    }

                    // Check for any steps whose descriptions in a workflow does not match
                    // the underlying step type name
                    if (m_flagDifferingStepNames)
                    {
                        IJTXStepType2 stepType = configMgr.GetStepTypeByID(step.StepTypeID) as IJTXStepType2;
                        if (!step.StepName.Equals(stepType.Name))
                        {
                            string message = "Workflow '" + workflow.Name + "', step name '" +
                                             step.StepName + "' does not match step type name '" + stepType.Name + "'";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                    }
                } // end for each step
            }     // end for each workflow
        }
        /// <summary>
        /// Helper function that runs all of those checks that operate on each job type;
        /// intended to make the checks slightly more efficient by running through them all
        /// at once rather than looping through all of the elements multiple times
        /// </summary>
        /// <param name="msgs">Add any GP messages to this object</param>
        /// <param name="errorCount">Counter used to track the number of problems found</param>
        /// <param name="logFileWriter">Object used to write error descriptions to a text file</param>
        private void ExecuteJobTypeChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter)
        {
            if (!m_flagInvalidJobTypeAssign &&
                !m_flagJobTypesWithoutWorkflows &&
                !m_flagMissingAoiMxds &&
                !m_flagMissingBaseMxds &&
                !m_flagNonActiveJobTypes)
            {
                return;
            }

            IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;

            // Put the items into a sorted list in order to make the output easier to
            // read/follow
            IJTXJobTypeSet allJobTypes = configMgr.JobTypes;
            SortedList <string, IJTXJobType3> allJobTypesSorted = new SortedList <string, IJTXJobType3>();

            for (int i = 0; i < allJobTypes.Count; i++)
            {
                allJobTypesSorted[allJobTypes.get_Item(i).Name] = allJobTypes.get_Item(i) as IJTXJobType3;
            }

            // Iterate through each item
            foreach (IJTXJobType3 jobType in allJobTypesSorted.Values)
            {
                if (m_flagInvalidJobTypeAssign)
                {
                    string assignedTo = jobType.DefaultAssignedTo;
                    if (jobType.DefaultAssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null)
                    {
                        string message = "Job Type '" + jobType.Name +
                                         "' assigned to unknown user '" + assignedTo + "'";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                    else if (jobType.DefaultAssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null)
                    {
                        string message = "Job Type '" + jobType.Name +
                                         "' assigned to unknown group '" + assignedTo + "'";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagJobTypesWithoutWorkflows)
                {
                    if (jobType.Workflow == null)
                    {
                        string message = "Job Type '" + jobType.Name + "' has no workflow defined";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagMissingAoiMxds)
                {
                    if (jobType.AOIMap == null)
                    {
                        string message = "Job Type '" + jobType.Name + "' has no AOI map defined";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagMissingBaseMxds)
                {
                    if (jobType.JobMap == null)
                    {
                        string message = "Job Type '" + jobType.Name +
                                         "' has no job map (a.k.a. basemap) defined";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }

                if (m_flagNonActiveJobTypes)
                {
                    if (jobType.State != jtxJobTypeState.jtxJobTypeStateActive)
                    {
                        string message = "Job Type '" + jobType.Name + "' is not active";
                        RecordMessage(message, msgs, logFileWriter);
                        errorCount++;
                    }
                }
            }
        }
        /// <summary>
        /// Helper function that runs all of those checks that operate on each job; intended
        /// to make the checks slightly more efficient by running through them all at once
        /// rather than looping through all of the elements multiple times
        /// </summary>
        /// <param name="msgs">Add any GP messages to this object</param>
        /// <param name="errorCount">Counter used to track the number of problems found</param>
        /// <param name="logFileWriter">Object used to write error descriptions to a text file</param>
        private void ExecuteJobChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter)
        {
            // Only continue executing this function if needed
            if (!m_flagInvalidJobAssign &&
                !m_flagIsSelfParent &&
                !m_flagJobsWithoutTypes)
            {
                return;
            }

            IJTXConfiguration3     configMgr  = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3;
            IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2;
            IJTXJobManager         jobMgr     = this.WmxDatabase.JobManager;

            // Use a database query as an alternate way of finding certain specific
            // problems with jobs.  Declare some of these ComReleaser objects to help
            // ensure that cursors, etc., are immediately released after they go out
            // of scope.

            // Check for jobs without any job types set (should be a DB error)
            if (m_flagJobsWithoutTypes)
            {
                using (ComReleaser cr1 = new ComReleaser(), cr2 = new ComReleaser())
                {
                    IFeatureWorkspace featureWorkspace = this.WmxDatabase.JTXWorkspace as IFeatureWorkspace;

                    // Get the name of the correct table from the jobs workspace, so
                    // that the table doesn't have to be owned by the connecting user.
                    string tableName = Common.WmauHelperFunctions.GetQualifiedTableName(Constants.JTX_TABLE_JTX_JOBS_TABLE, this.WmxDatabase.JTXWorkspace);

                    ITable jobsTable = featureWorkspace.OpenTable(tableName);
                    cr1.ManageLifetime(jobsTable);

                    IQueryFilter query = new QueryFilterClass();
                    query.WhereClause = Constants.FIELD_JOBTYPEID + " IS NULL";
                    ICursor searchCursor = jobsTable.Search(query, true);
                    cr2.ManageLifetime(searchCursor);

                    // Store the ID and name of each job matching this query
                    int  idIndex   = jobsTable.FindField(Constants.FIELD_JOBID);
                    int  nameIndex = jobsTable.FindField(Constants.FIELD_JOBNAME);
                    IRow row       = null;
                    while ((row = searchCursor.NextRow()) != null)
                    {
                        string idStr   = row.get_Value(idIndex).ToString();
                        string nameStr = row.get_Value(nameIndex).ToString();
                        string msg     = "Job " + idStr + " (" + nameStr + ") has no associated job type";
                        RecordMessage(msg, msgs, logFileWriter);
                        errorCount++;
                    }
                }
            }

            // Check for jobs that are their own parent job
            if (m_flagIsSelfParent)
            {
                using (ComReleaser cr1 = new ComReleaser(), cr2 = new ComReleaser())
                {
                    IFeatureWorkspace featureWorkspace = this.WmxDatabase.JTXWorkspace as IFeatureWorkspace;

                    // Get the name of the correct table from the jobs workspace, so
                    // that the table doesn't have to be owned by the connecting user.
                    string tableName = Common.WmauHelperFunctions.GetQualifiedTableName(Constants.JTX_TABLE_JTX_JOBS_TABLE, this.WmxDatabase.JTXWorkspace);

                    ITable jobsTable = featureWorkspace.OpenTable(tableName);
                    cr1.ManageLifetime(jobsTable);

                    const string C_FIELD_PARENT_JOB = "PARENT_JOB";
                    IQueryFilter query = new QueryFilterClass();
                    query.WhereClause = Constants.FIELD_JOBID + " = " + C_FIELD_PARENT_JOB;
                    ICursor searchCursor = jobsTable.Search(query, true);
                    cr2.ManageLifetime(searchCursor);

                    // Store the ID and name of each job matching this query
                    int  idIndex   = jobsTable.FindField(Constants.FIELD_JOBID);
                    int  nameIndex = jobsTable.FindField(Constants.FIELD_JOBNAME);
                    IRow row       = null;
                    while ((row = searchCursor.NextRow()) != null)
                    {
                        string idStr   = row.get_Value(idIndex).ToString();
                        string nameStr = row.get_Value(nameIndex).ToString();
                        string msg     = "Job " + idStr + " (" + nameStr + ") is its own parent";
                        RecordMessage(msg, msgs, logFileWriter);
                        errorCount++;
                    }
                }
            }

            // See if there are any checks selected for which we should iterate through
            // all of the jobs using the WMX interfaces
            if (m_flagInvalidJobAssign)
            {
                // Put the items into a sorted list in order to make the output easier to
                // read/follow
                IJTXJobSet allJobs = jobMgr.GetAllJobs();
                SortedList <int, IJTXJob3> allJobsSorted = new SortedList <int, IJTXJob3>();
                for (int i = 0; i < allJobs.Count; i++)
                {
                    allJobsSorted[allJobs.get_Item(i).ID] = allJobs.get_Item(i) as IJTXJob3;
                }

                // Iterate over all of the jobs
                foreach (IJTXJob3 job in allJobsSorted.Values)
                {
                    string assignedTo = job.AssignedTo;

                    // Check for any existing jobs with an invalid job assignment.  NOTE: only
                    // want to flag jobs that are not closed
                    if (m_flagInvalidJobAssign && job.Stage != jtxJobStage.jtxJobStageClosed)
                    {
                        if (job.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null)
                        {
                            string message = "Job '" + job.ID.ToString() +
                                             "' assigned to unknown user '" + assignedTo + "'";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                        else if (job.AssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null)
                        {
                            string message = "Job '" + job.ID.ToString() +
                                             "' assigned to unknown group '" + assignedTo + "'";
                            RecordMessage(message, msgs, logFileWriter);
                            errorCount++;
                        }
                    }
                }
            }
        }