Пример #1
0
        /// <summary>
        /// Builds a domain consisting of the IDs of every job in the database that
        /// has not already been closed.
        /// </summary>
        /// <param name="wmxDb">A reference to the active Workflow Manager database</param>
        /// <returns>A coded value domain as an IGPDomain</returns>
        public static IGPDomain BuildNonClosedJobIdDomain(IJTXDatabase3 wmxDb)
        {
            IGPCodedValueDomain domain = new GPCodedValueDomainClass();

            // Set up a query filter to return only those jobs that are not closed
            IQueryFilter queryFilter = new QueryFilterClass();

            queryFilter.WhereClause =
                ESRI.ArcGIS.JTX.Utilities.Constants.FIELD_STAGE + " <> '" +
                ((int)jtxJobStage.jtxJobStageClosed).ToString() + "'";

            IJTXJobSet nonClosedJobs = wmxDb.JobManager.GetJobsByQuery(queryFilter);

            // Iterate through this job list, sorting the IDs
            SortedList <int, string> sortedJobIds = new SortedList <int, string>();

            for (int i = 0; i < nonClosedJobs.Count; i++)
            {
                IJTXJob3 job = nonClosedJobs.get_Item(i) as IJTXJob3;
                sortedJobIds[job.ID] = null;
            }

            // Build a GP domain from the sorted job IDs.
            foreach (int id in sortedJobIds.Keys)
            {
                IGPValue tempGpVal = new GPLongClass();
                tempGpVal.SetAsText(id.ToString());
                domain.AddCode(tempGpVal, id.ToString());
            }

            return(domain as IGPDomain);
        }
        /// <summary>
        /// Find those priority levels in the database that are not being used by any
        /// job or job type.
        /// </summary>
        /// <returns>The total number of orphaned items found</returns>
        private int UpdateOrphanedPriorityTypes()
        {
            Dictionary <int, string> usedTypes = new Dictionary <int, string>();
            IJTXDatabase3            wmxDb     = this.WmxDatabase;

            // Check all the jobs for priorities currently in use
            IJTXJobSet allJobs = wmxDb.JobManager.GetAllJobs();

            for (int i = 0; i < allJobs.Count; i++)
            {
                IJTXJob3 job = allJobs.get_Item(i) as IJTXJob3;
                if (!usedTypes.ContainsKey(job.Priority.Value))
                {
                    usedTypes[job.Priority.Value] = job.Priority.Name;
                }
            }

            // Check the template job types for default priorities in use
            IJTXJobTypeSet allJobTypes = wmxDb.ConfigurationManager.JobTypes;

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

                IJTXJobType3 jobType = allJobTypes.get_Item(i) as IJTXJobType3;
                if (!usedTypes.ContainsKey(jobType.DefaultPriority.Value))
                {
                    usedTypes[jobType.DefaultPriority.Value] = jobType.DefaultPriority.Name;
                }
            }

            // Loop over all of the priorities.  For anything whose name is not contained
            // in the "used" list, add it to the "unused" list.  If all of the items are
            // used, don't bother trying to add to the unused list.
            IJTXPrioritySet allTypes = wmxDb.ConfigurationManager.Priorities;

            if (usedTypes.Count != allTypes.Count)
            {
                for (int i = 0; i < allTypes.Count; i++)
                {
                    IJTXPriority priority = allTypes.get_Item(i) as IJTXPriority;
                    if (!usedTypes.ContainsKey(priority.Value))
                    {
                        m_unusedPriorities[priority.Value] = priority.Name;
                    }
                }
            }

            return(m_unusedPriorities.Count);
        }
        ////////////////////////////////////////////////////////////////////////
        // METHOD: CreateJobs
        private int CreateJobs(IJTXJob2 pParentJob)
        {
            try
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                bool bAutoCommit = ConfigurationCache.AutoCommitWorkflow;

                m_ipDatabase.LogMessage(5, 2000, "CreateJobs");

                // Set the job template values
                IJTXJobManager2 pJobMan = m_ipDatabase.JobManager as IJTXJobManager2;
                IJTXJobDescription pJobDescription = new JTXJobDescriptionClass();

                pJobDescription.Description = pParentJob.Description;
                pJobDescription.Priority = pParentJob.Priority;
                pJobDescription.ParentJobId = pParentJob.ID;

                pJobDescription.StartDate = pParentJob.StartDate;

                if (m_dueDate != Constants.NullDate)
                    pJobDescription.DueDate = m_dueDate;
                else if (m_duration > 0)
                    pJobDescription.DueDate = System.DateTime.Now.AddDays(m_duration);
                else
                    pJobDescription.DueDate = pParentJob.DueDate;

                if (!String.IsNullOrEmpty(m_paramAssignToGroup))
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeGroup;
                    pJobDescription.AssignedTo = m_paramAssignToGroup;
                }
                else if (!String.IsNullOrEmpty(m_paramAssignToUser))
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeUser;
                    pJobDescription.AssignedTo = m_paramAssignToUser;
                }
                else
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeUnassigned;
                }

                pJobDescription.OwnedBy = ConfigurationCache.GetCurrentJTXUser().UserName;

                if (pParentJob.ActiveDatabase != null)
                    pJobDescription.DataWorkspaceID = pParentJob.ActiveDatabase.DatabaseID;

                // Set the parent version.  This only makes sense if the active workspace has been set
                if (pJobDescription.DataWorkspaceID != null)
                {
                    if (m_paramCreateVersionType == CreateVersionType.None
                        || m_paramCreateVersionType == CreateVersionType.UseParentJobsVersion)
                        pJobDescription.ParentVersionName = pParentJob.VersionName;	// This has to be set here because setting the job workspace resets the value
                    else if (m_paramCreateVersionType == CreateVersionType.UseJobTypeDefaultSettings)
                    {
                        IJTXJobType pJobType = m_ipDatabase.ConfigurationManager.GetJobType(m_paramJobTypeName);
                        if (pJobType != null)
                            pJobDescription.ParentVersionName = pJobType.DefaultParentVersionName;
                    }
                    else if (m_paramCreateVersionType == CreateVersionType.UseParentJobsDefaultVersion)
                        pJobDescription.ParentVersionName = pParentJob.JobType.DefaultParentVersionName;
                    else if (m_paramCreateVersionType == CreateVersionType.UseParentJobsParentVersion)
                        pJobDescription.ParentVersionName = pParentJob.ParentVersion;
                }

                // Determine the number of jobs to make
                m_ipDatabase.LogMessage(5, 2000, "Before Determining Number of Jobs");

                IArray aoiList = null;
                int numJobs;
                if (!GetNumberOfJobs(pParentJob, ref aoiList, out numJobs))
                    return 1;

                if (numJobs <= 0)
                {
                    MessageBox.Show(Properties.Resources.ZeroJobCount);
                    return 0;
                }
                pJobDescription.AOIList = aoiList;
                m_ipDatabase.LogMessage(5, 2000, "After Determining Number of Jobs");


                // Create the job objects
                m_ipDatabase.LogMessage(5, 2000, "Before CreateJobs");
                pJobDescription.JobTypeName = m_paramJobTypeName;
                IJTXExecuteInfo pExecInfo;
                m_ipJobs = pJobMan.CreateJobsFromDescription(pJobDescription, numJobs, true, out pExecInfo);
                m_ipDatabase.LogMessage(5, 2000, "After CreateJobs");


                // Populate the job data
                for (int i = 0; i < m_ipJobs.Count; ++i)
                {
                    IJTXJob pJob = m_ipJobs.get_Item(i);

                    SetJobProperties(pJobMan, pJob, pParentJob);
                }
                return 1;
            }
            catch (COMException ex)
            {
                if (ex.ErrorCode == (int)fdoError.FDO_E_SE_INVALID_COLUMN_VALUE)
                {
                    MessageBox.Show(Properties.Resources.InvalidColumn, Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
                return 0;
            }
            catch (Exception ex2)
            {
                MessageBox.Show(ex2.Message, Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return 0;
            }
            finally
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            }
        }
        /// <summary>
        /// Find those users in the database who are not being referenced in any way
        /// </summary>
        /// <returns>The total number of orphaned items found</returns>
        private int UpdateOrphanedUsers()
        {
            SortedList <string, string> unusedItems = new SortedList <string, string>();
            IJTXDatabase3      wmxDb     = this.WmxDatabase;
            IJTXConfiguration3 configMgr = wmxDb.ConfigurationManager as IJTXConfiguration3;
            IJTXJobManager     jobMgr    = wmxDb.JobManager;
            IJTXUserSet        allUsers  = configMgr.Users;

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

            // Get all of the users who are members of a group
            IJTXUserGroupSet allGroups = configMgr.UserGroups;

            for (int i = 0; i < allGroups.Count; i++)
            {
                IJTXUserGroup2 group = allGroups.get_Item(i) as IJTXUserGroup2;
                for (int j = 0; j < group.Users.Count; j++)
                {
                    IJTXUser3 user = group.Users.get_Item(j) as IJTXUser3;
                    usedItems[user.UserName] = user.FullName;
                }
            }

            // If necessary, add in the users who have jobs assigned to them
            if (usedItems.Count < allUsers.Count)
            {
                IJTXJobSet allJobs = jobMgr.GetAllJobs();
                for (int i = 0; i < allJobs.Count; i++)
                {
                    IJTXJob3 job = allJobs.get_Item(i) as IJTXJob3;
                    if (job.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser)
                    {
                        IJTXUser3 user = configMgr.GetUser(job.AssignedTo) as IJTXUser3;

                        // It's possible for a user to have a job assigned, but have
                        // already been removed from the DB.  Throw an exception in
                        // this case, as the DB needs to be cleaned up.
                        if (user == null)
                        {
                            throw new WmauException(WmauErrorCodes.C_USER_NOT_FOUND_ERROR);
                        }
                        usedItems[user.UserName] = user.FullName;
                    }
                }
            }

            // If necessary, add in the users who have a job type's default assignment
            // set to them
            if (usedItems.Count < allUsers.Count)
            {
                IJTXJobTypeSet allJobTypes = configMgr.JobTypes;
                for (int i = 0; i < allJobTypes.Count; i++)
                {
                    // TODO: Exclude orphaned job types

                    IJTXJobType3 jobType = allJobTypes.get_Item(i) as IJTXJobType3;
                    if (jobType.DefaultAssignedType == jtxAssignmentType.jtxAssignmentTypeUser)
                    {
                        IJTXUser3 user = configMgr.GetUser(jobType.DefaultAssignedTo) as IJTXUser3;

                        // It's possible for a user to have a job assigned, but have
                        // already been removed from the DB.  Throw an exception in
                        // this case, as the DB needs to be cleaned up.
                        if (user == null)
                        {
                            throw new WmauException(WmauErrorCodes.C_USER_NOT_FOUND_ERROR);
                        }
                        usedItems[user.UserName] = user.FullName;
                    }
                }
            }

            // If necessary, add in the users who have steps assigned to them
            // by default
            if (usedItems.Count < allUsers.Count)
            {
                IJTXWorkflowSet allWorkflows = configMgr.Workflows;
                for (int i = 0; i < allWorkflows.Count; i++)
                {
                    // Skip over unused workflows
                    IJTXWorkflow workflow = allWorkflows.get_Item(i);
                    if (m_unusedWorkflows.Keys.Contains(workflow.ID))
                    {
                        continue;
                    }

                    // Examine the other items
                    IJTXWorkflowConfiguration workflowCfg = allWorkflows.get_Item(i) as IJTXWorkflowConfiguration;
                    int[] workflowStepIds = workflowCfg.GetAllSteps();
                    foreach (int j in workflowStepIds)
                    {
                        IJTXStep3 step = workflowCfg.GetStep(j) as IJTXStep3;
                        if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser)
                        {
                            IJTXUser3 user = configMgr.GetUser(step.AssignedTo) as IJTXUser3;

                            // It's possible for a user to have a job assigned, but have
                            // already been removed from the DB.  Throw an exception in
                            // this case, as the DB needs to be cleaned up.
                            if (user == null)
                            {
                                throw new WmauException(WmauErrorCodes.C_USER_NOT_FOUND_ERROR);
                            }
                            usedItems[user.UserName] = user.FullName;
                        }
                    }
                }
            }

            // Loop over all the users in the DB, looking for anything
            // that we didn't identify as "in use"
            for (int i = 0; i < allUsers.Count; i++)
            {
                IJTXUser3 item = allUsers.get_Item(i) as IJTXUser3;
                if (!usedItems.ContainsKey(item.UserName))
                {
                    m_unusedUsers[item.UserName] = item.FullName;
                }
            }

            return(m_unusedUsers.Count);
        }
        /// <summary>
        /// Find those status types in the database that are not being used by any step.
        /// </summary>
        /// <returns>The total number of orphaned items found</returns>
        private int UpdateOrphanedStatusTypes()
        {
            Dictionary <int, int> usedStatusTypes = new Dictionary <int, int>();
            IJTXDatabase3         wmxDb           = this.WmxDatabase;

            string[] coreStatusNames =
            {
                C_STATUS_CLOSED,
                C_STATUS_CREATED,
                C_STATUS_DONE_WORKING,
                C_STATUS_READY_TO_WORK,
                C_STATUS_WORKING
            };

            IJTXConfiguration3 configMgr = wmxDb.ConfigurationManager as IJTXConfiguration3;

            // Iterate through each job currently in the system, adding the status types used
            // by these jobs
            IJTXJobSet jobs = wmxDb.JobManager.GetAllJobs();

            for (int i = 0; i < jobs.Count; i++)
            {
                IJTXJob3 job = jobs.get_Item(i) as IJTXJob3;
                if (job.Status != null)
                {
                    usedStatusTypes[job.Status.ID] = job.Status.ID;
                }
            }

            // Iterate through each workflow, building up the list of used status types
            // based on the statuses that are assigned by each step
            IJTXWorkflowSet workflows = configMgr.Workflows;

            for (int i = 0; i < workflows.Count; i++)
            {
                // Skip over those workflows that aren't in use
                IJTXWorkflow workflow = workflows.get_Item(i);
                if (m_unusedWorkflows.Keys.Contains(workflow.ID))
                {
                    continue;
                }

                // Examine the remaining workflows
                IJTXWorkflowConfiguration workflowCfg = workflows.get_Item(i) as IJTXWorkflowConfiguration;
                int[] stepIds = workflowCfg.GetAllSteps();
                foreach (int stepId in stepIds)
                {
                    IJTXStep3 step = workflowCfg.GetStep(stepId) as IJTXStep3;
                    usedStatusTypes[step.StatusID] = step.StatusID;
                }
            }

            // Add the status types used by Workflow Manager itself
            foreach (string s in coreStatusNames)
            {
                IJTXStatus2 status = configMgr.GetStatus(s) as IJTXStatus2;

                // Avoid problems if someone deleted one of these mandatory types from the database
                if (status != null)
                {
                    int id = status.ID;
                    usedStatusTypes[id] = id;
                }
            }

            // Get the complete list of status types in the database
            IJTXStatusSet allStatusTypes = configMgr.Statuses;

            // Loop over all of the status types.  For anything whose ID is not contained
            // in the "used" list, add it to the "unused" list. If all of the items are
            // used, don't bother trying to add to the unused list.
            if (usedStatusTypes.Count != allStatusTypes.Count)
            {
                for (int i = 0; i < allStatusTypes.Count; i++)
                {
                    IJTXStatus2 statusType = allStatusTypes.get_Item(i) as IJTXStatus2;
                    if (!usedStatusTypes.ContainsKey(statusType.ID))
                    {
                        m_unusedStatusTypes[statusType.ID] = statusType.Name;
                    }
                }
            }

            return(m_unusedStatusTypes.Count);
        }
        /// <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++;
                        }
                    }
                }
            }
        }
        ////////////////////////////////////////////////////////////////////////
        // METHOD: CreateJobs
        private int CreateJobs(IJTXJob2 pParentJob)
        {
            try
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                bool bAutoCommit = ConfigurationCache.AutoCommitWorkflow;

                m_ipDatabase.LogMessage(5, 2000, "CreateJobs");

                // Set the job template values
                IJTXJobManager2    pJobMan         = m_ipDatabase.JobManager as IJTXJobManager2;
                IJTXJobDescription pJobDescription = new JTXJobDescriptionClass();

                pJobDescription.Description = pParentJob.Description;
                pJobDescription.Priority    = pParentJob.Priority;
                pJobDescription.ParentJobId = pParentJob.ID;

                pJobDescription.StartDate = pParentJob.StartDate;

                if (m_dueDate != Constants.NullDate)
                {
                    pJobDescription.DueDate = m_dueDate;
                }
                else if (m_duration > 0)
                {
                    pJobDescription.DueDate = System.DateTime.Now.AddDays(m_duration);
                }
                else
                {
                    pJobDescription.DueDate = pParentJob.DueDate;
                }

                if (!String.IsNullOrEmpty(m_paramAssignToGroup))
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeGroup;
                    pJobDescription.AssignedTo   = m_paramAssignToGroup;
                }
                else if (!String.IsNullOrEmpty(m_paramAssignToUser))
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeUser;
                    pJobDescription.AssignedTo   = m_paramAssignToUser;
                }
                else
                {
                    pJobDescription.AssignedType = jtxAssignmentType.jtxAssignmentTypeUnassigned;
                }

                pJobDescription.OwnedBy = ConfigurationCache.GetCurrentJTXUser().UserName;

                if (pParentJob.ActiveDatabase != null)
                {
                    pJobDescription.DataWorkspaceID = pParentJob.ActiveDatabase.DatabaseID;
                }

                // Set the parent version.  This only makes sense if the active workspace has been set
                if (pJobDescription.DataWorkspaceID != null)
                {
                    if (m_paramCreateVersionType == CreateVersionType.None ||
                        m_paramCreateVersionType == CreateVersionType.UseParentJobsVersion)
                    {
                        pJobDescription.ParentVersionName = pParentJob.VersionName;     // This has to be set here because setting the job workspace resets the value
                    }
                    else if (m_paramCreateVersionType == CreateVersionType.UseJobTypeDefaultSettings)
                    {
                        IJTXJobType pJobType = m_ipDatabase.ConfigurationManager.GetJobType(m_paramJobTypeName);
                        if (pJobType != null)
                        {
                            pJobDescription.ParentVersionName = pJobType.DefaultParentVersionName;
                        }
                    }
                    else if (m_paramCreateVersionType == CreateVersionType.UseParentJobsDefaultVersion)
                    {
                        pJobDescription.ParentVersionName = pParentJob.JobType.DefaultParentVersionName;
                    }
                    else if (m_paramCreateVersionType == CreateVersionType.UseParentJobsParentVersion)
                    {
                        pJobDescription.ParentVersionName = pParentJob.ParentVersion;
                    }
                }

                // Determine the number of jobs to make
                m_ipDatabase.LogMessage(5, 2000, "Before Determining Number of Jobs");

                IArray aoiList = null;
                int    numJobs;
                if (!GetNumberOfJobs(pParentJob, ref aoiList, out numJobs))
                {
                    return(1);
                }

                if (numJobs <= 0)
                {
                    MessageBox.Show(Properties.Resources.ZeroJobCount);
                    return(0);
                }
                pJobDescription.AOIList = aoiList;
                m_ipDatabase.LogMessage(5, 2000, "After Determining Number of Jobs");


                // Create the job objects
                m_ipDatabase.LogMessage(5, 2000, "Before CreateJobs");
                pJobDescription.JobTypeName = m_paramJobTypeName;
                IJTXExecuteInfo pExecInfo;
                m_ipJobs = pJobMan.CreateJobsFromDescription(pJobDescription, numJobs, true, out pExecInfo);
                m_ipDatabase.LogMessage(5, 2000, "After CreateJobs");


                // Populate the job data
                for (int i = 0; i < m_ipJobs.Count; ++i)
                {
                    IJTXJob pJob = m_ipJobs.get_Item(i);

                    SetJobProperties(pJobMan, pJob, pParentJob);
                }
                return(1);
            }
            catch (COMException ex)
            {
                if (ex.ErrorCode == (int)fdoError.FDO_E_SE_INVALID_COLUMN_VALUE)
                {
                    MessageBox.Show(Properties.Resources.InvalidColumn, Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
                return(0);
            }
            catch (Exception ex2)
            {
                MessageBox.Show(ex2.Message, Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return(0);
            }
            finally
            {
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            }
        }