Exemple #1
0
        public Control GetConfigurationControl(AlteryxGuiToolkit.Document.Properties docProperties, XmlElement eConfig, XmlElement[] eIncomingMetaInfo, int nToolId, string strToolName)
        {
            // This method is called by Alteryx to initialize this configuration control from data
            // stored in the module containing this tool.

            // Tool configuration is handled through an XML document managed by Alteryx.  When it is
            // time to initialize this control (generally when it is made visible to the user), this
            // method is called, passing the XML document in with the eConfig parameter.

            // When this tool is connected to one or more upstream data providers, the structure of
            // each data stream is passed as an entry in the eIncomingMetaInfo array.  This data can
            // then be used to dynamically construct your UI based on the type of input.

            // Since this tool is an input tool, the eIncomingMetaInfo parameter will be empty.
            // We will use the information in eConfig to populate the XmlFile text box.  This will
            // cause the file to be examined if it exists (through the XmlFile_TextChanged event
            // handler) in order to populate the sample information.  We will then use the remaining
            // information in eConfig to set the field properties if that information exists.

            // Call LoadFromConfiguration to get the xml file name and field information from eConfig.
            XmlInputConfiguration xmlConfig = XmlInputConfiguration.LoadFromConfiguration(eConfig);

            if (xmlConfig != null)
            {
                // Update the XmlFile and ElementName textboxes.
                txtUserName.Text = xmlConfig.UserName;
                txtPassword.Text = xmlConfig.Password;
                cboFolderToSearch.SelectedValue = xmlConfig.Folder;
                txtAttachmentPath.Text          = xmlConfig.AttachmentPath;
                txtQueryString.Text             = xmlConfig.QueryString;

                foreach (XmlInputField field in xmlConfig.Fields)
                {
                    // Use a little LINQ to find the row in the field list that
                    // corresponds to the current field.
                    var item = clbFields.Items.Cast <KeyValuePair <string, string> >().Where(x => x.Value == field.Name).FirstOrDefault();

                    if (clbFields.Items.IndexOf(item) != -1)
                    {
                        clbFields.SetItemChecked(clbFields.Items.IndexOf(item), true);
                    }
                }
            }

            return(this);
        }
Exemple #2
0
        // Creates a new instance of the XmlInputConfiguration class based on the information
        // in the eConfig xml element.  This is the eConfig that Alteryx provides in the
        // IPluginConfiguration.GetConfigurationControl() method.
        public static XmlInputConfiguration LoadFromConfiguration(XmlElement eConfig)
        {
            // Get the configuration values from the XML config elements to be place in their corresponding fields in the UI.
            XmlElement userName = eConfig.SelectSingleNode("UserName") as XmlElement;

            XmlElement password = eConfig.SelectSingleNode("Password") as XmlElement;

            XmlElement folder = eConfig.SelectSingleNode("Folder") as XmlElement;

            XmlElement attachmentPath = eConfig.SelectSingleNode("AttachmentPath") as XmlElement;

            XmlElement queryString = eConfig.SelectSingleNode("QueryString") as XmlElement;

            if (userName != null && password != null)
            {
                // Create the new XmlInputConfiguration object.
                XmlInputConfiguration xmlConfig = new XmlInputConfiguration(userName.InnerText, password.InnerText, Convert.ToInt16(folder.InnerText), attachmentPath.InnerText, queryString.InnerText);

                // Find all of the Field elements in the configuration.
                XmlNodeList fields = eConfig.SelectNodes("Fields/Field");
                foreach (XmlElement fieldElement in fields)
                {
                    // For each field element, add a new field to the object with the name, type, size and scale info.
                    string name = fieldElement.GetAttribute("Name");
                    AlteryxRecordInfoNet.FieldType type = AlteryxRecordInfoNet.FieldType.E_FT_String;
                    Enum.TryParse <AlteryxRecordInfoNet.FieldType>(fieldElement.GetAttribute("Type"), out type);
                    int size = 0;
                    int.TryParse(fieldElement.GetAttribute("Size"), out size);
                    int scale = 0;
                    int.TryParse(fieldElement.GetAttribute("Scale"), out scale);

                    xmlConfig.AddField(name, type, size, scale);
                }

                return(xmlConfig);
            }

            return(null);
        }
        // Creates a new instance of the XmlInputConfiguration class based on the information
        // in the eConfig xml element.  This is the eConfig that Alteryx provides in the
        // IPluginConfiguration.GetConfigurationControl() method.
        public static XmlInputConfiguration LoadFromConfiguration(XmlElement eConfig)
        {
            // Get the configuration values from the XML config elements to be place in their corresponding fields in the UI.
            XmlElement userName = (XmlElement)eConfig.SelectSingleNode("UserName");

            XmlElement password = (XmlElement)eConfig.SelectSingleNode("Password");

            XmlElement exchangeVersion = (XmlElement)eConfig.SelectSingleNode("ExchangeVersion");

            XmlElement useManualServiceURL = (XmlElement)eConfig.SelectSingleNode("UseManualServiceURL");

            XmlElement serviceURL = (XmlElement)eConfig.SelectSingleNode("ServiceURL");

            XmlElement useDifferentMailbox = (XmlElement)eConfig.SelectSingleNode("UseDifferentMailbox");

            XmlElement mailbox = (XmlElement)eConfig.SelectSingleNode("Mailbox");

            XmlElement folder = (XmlElement)eConfig.SelectSingleNode("Folder");

            XmlElement includeRecurringEvents = (XmlElement)eConfig.SelectSingleNode("IncludeRecurringEvents");

            XmlElement startDate = (XmlElement)eConfig.SelectSingleNode("StartDate");

            XmlElement endDate = (XmlElement)eConfig.SelectSingleNode("EndDate");

            XmlElement attachmentPath = (XmlElement)eConfig.SelectSingleNode("AttachmentPath");

            XmlElement queryString = (XmlElement)eConfig.SelectSingleNode("QueryString");

            XmlElement includeSubFolders = (XmlElement)eConfig.SelectSingleNode("IncludeSubFolders");

            XmlElement subFolderName = (XmlElement)eConfig.SelectSingleNode("SubFolderName");

            XmlElement skipRootFolder = (XmlElement)eConfig.SelectSingleNode("SkipRootFolder");

            XmlElement useUniqueFileName = (XmlElement)eConfig.SelectSingleNode("UseUniqueFileName");

            XmlElement attachmentFilter = (XmlElement)eConfig.SelectSingleNode("AttachmentFilter");

            if (userName != null && password != null)
            {
                // Create the new XmlInputConfiguration object.
                XmlInputConfiguration xmlConfig = new XmlInputConfiguration(userName.InnerString(), password.InnerString(), exchangeVersion.InnerInt <ExchangeVersion>(), useManualServiceURL.InnerBoolean(), serviceURL.InnerString(), useDifferentMailbox.InnerBoolean(), mailbox.InnerString(), folder.InnerInt <WellKnownFolderName>(), includeRecurringEvents.InnerBoolean(), startDate.InnerDateTime(), endDate.InnerDateTime(), attachmentPath.InnerString(), queryString.InnerString(), includeSubFolders.InnerBoolean(), subFolderName.InnerString(), skipRootFolder.InnerBoolean(), useUniqueFileName.InnerBoolean(), attachmentFilter.InnerString());

                // Find all of the Field elements in the configuration.
                XmlNodeList fields = eConfig.SelectNodes("Fields/Field");
                foreach (XmlElement fieldElement in fields)
                {
                    // For each field element, add a new field to the object with the name, type, size and scale info.
                    string name = fieldElement.GetAttribute("Name");
                    AlteryxRecordInfoNet.FieldType type = AlteryxRecordInfoNet.FieldType.E_FT_String;
                    Enum.TryParse <AlteryxRecordInfoNet.FieldType>(fieldElement.GetAttribute("Type"), out type);
                    int size = 0;
                    int.TryParse(fieldElement.GetAttribute("Size"), out size);
                    int scale = 0;
                    int.TryParse(fieldElement.GetAttribute("Scale"), out scale);

                    xmlConfig.AddField(name, type, size, scale);
                }

                return(xmlConfig);
            }

            return(null);
        }
        // Called by Alteryx for an Input tool to request all of the records.
        public bool PI_PushAllRecords(long nRecordLimit)
        {
            // The nRecordLimit parameter specifies the maximum number of records that
            // should be provided, or -1 for unlimited.  If it is -1, set it to
            // long.MaxValue to make the processing easier later on.  Sometimes Alteryx
            // will call this function with a record limit of 0 just to get the output
            // record configuration.
            if (nRecordLimit < 0)
            {
                nRecordLimit = long.MaxValue;
            }

            m_engineInterface.OutputMessage(m_nToolId, AlteryxRecordInfoNet.MessageStatus.STATUS_Info, nRecordLimit.ToString());

            if (m_engineInterface.GetInitVar("UpdateOnly") == "True")
            {
                m_engineInterface.OutputMessage(m_nToolId, AlteryxRecordInfoNet.MessageStatus.STATUS_Complete, nRecordLimit.ToString());
            }
            else
            {
                // Get the configuration section out of the properties xml that was passed
                // into PI_Init() and use it to determine the xml file, container element,
                // and field configuration for our tool.

                XmlElement            configXml = m_xmlProperties.SelectSingleNode("Configuration") as XmlElement;
                XmlInputConfiguration xmlConfig = XmlInputConfiguration.LoadFromConfiguration(configXml);

                if (xmlConfig == null)
                {
                    throw new ApplicationException("Invalid configuration.  Ensure that the input file is set correctly.");
                }

                if (xmlConfig.Fields.Count == 0)
                {
                    throw new ApplicationException("There are no fields.  Make sure your container element is set properly.");
                }

                // Create a new RecordInfo object to describe our outgoing message records and
                // configure it based on the field information in our saved configuration.
                AlteryxRecordInfoNet.RecordInfo recordInfoOut = new AlteryxRecordInfoNet.RecordInfo();
                foreach (XmlInputField field in xmlConfig.Fields)
                {
                    // For each field in our configuration, add it to our RecordInfo object.
                    recordInfoOut.AddField(field.Name, field.FieldType, field.Size, field.Scale, "", "");
                }

                // Use the new RecordInfo object to initialize the PluginOutputConnectionHelper.
                // The PluginOutputConnectionHelper can't be used until this step is performed.
                m_outputHelper.Init(recordInfoOut, "Message Output", null, m_xmlProperties);

                // Create a Record object to hold the data for each outgoing message record.
                AlteryxRecordInfoNet.Record recordOut = recordInfoOut.CreateRecord();

                // Create a new RecordInfo object to describe our outgoing attachment records and
                // configure it based on the field information in our saved configuration.
                AlteryxRecordInfoNet.RecordInfo recordInfoOut_AttachmentPaths = new AlteryxRecordInfoNet.RecordInfo();

                // For each field in our configuration, add it to our RecordInfo object.
                recordInfoOut_AttachmentPaths.AddField("Id", AlteryxRecordInfoNet.FieldType.E_FT_String, 4000, 0, "", "");
                recordInfoOut_AttachmentPaths.AddField("AttachmentPath", AlteryxRecordInfoNet.FieldType.E_FT_String, 4000, 0, "", "");

                // Use the new RecordInfo object to initialize the PluginOutputConnectionHelper.
                // The PluginOutputConnectionHelper can't be used until this step is performed.
                m_attachmentOutputHelper.Init(recordInfoOut_AttachmentPaths, "Attachment Output", null, m_xmlProperties);

                // Create a Record object to hold the data for each outgoing attachment record.
                AlteryxRecordInfoNet.Record recordOut_AttachmentPaths = recordInfoOut_AttachmentPaths.CreateRecord();

                // Define the necessary PropertyDefinitionBase objects for each field in the XML configuration document.
                PropertyDefinitionBase[] propertyDefinitionBase = new PropertyDefinitionBase[xmlConfig.Fields.Count];

                for (int i = 0; i < xmlConfig.Fields.Count; i++)
                {
                    if ((WellKnownFolderName)xmlConfig.Folder == WellKnownFolderName.Calendar && typeof(AppointmentSchema).GetField(xmlConfig.Fields[i].Name) != null)
                    {
                        propertyDefinitionBase[i] = (PropertyDefinitionBase)typeof(AppointmentSchema).GetField(xmlConfig.Fields[i].Name).GetValue(null);
                    }
                    else if ((WellKnownFolderName)xmlConfig.Folder == WellKnownFolderName.Inbox && typeof(EmailMessageSchema).GetField(xmlConfig.Fields[i].Name) != null)
                    {
                        propertyDefinitionBase[i] = (PropertyDefinitionBase)typeof(EmailMessageSchema).GetField(xmlConfig.Fields[i].Name).GetValue(null);
                    }
                    else if ((WellKnownFolderName)xmlConfig.Folder == WellKnownFolderName.Tasks && typeof(TaskSchema).GetField(xmlConfig.Fields[i].Name) != null)
                    {
                        propertyDefinitionBase[i] = (PropertyDefinitionBase)typeof(TaskSchema).GetField(xmlConfig.Fields[i].Name).GetValue(null);
                    }
                    else
                    {
                        propertyDefinitionBase[i] = (PropertyDefinitionBase)typeof(ItemSchema).GetField(xmlConfig.Fields[i].Name).GetValue(null);
                    }
                }

                // Assign the configuration settings and field list to the OutlookEmail object.
                OutlookEmail email = new OutlookEmail()
                {
                    UserName = xmlConfig.UserName, Password = xmlConfig.Password, ExchangeServerVersion = xmlConfig.ExchangeVersion, UseManualServiceURL = xmlConfig.UseManualServiceURL, ServiceURL = xmlConfig.ServiceURL, UseDifferentMailbox = xmlConfig.UseDifferentMailbox, Mailbox = xmlConfig.Mailbox, Folder = (WellKnownFolderName)xmlConfig.Folder, IncludeRecurringEvents = xmlConfig.IncludeRecurringEvents, StartDate = xmlConfig.StartDate, EndDate = xmlConfig.EndDate, AttachmentPath = xmlConfig.AttachmentPath, QueryString = xmlConfig.QueryString, IncludeSubFolders = xmlConfig.IncludeSubFolders, SubFolderName = xmlConfig.SubFolderName, SkipRootFolder = xmlConfig.SkipRootFolder, UseUniqueFileName = xmlConfig.UseUniqueFileName, AttachmentFilter = xmlConfig.AttachmentFilter
                };
                email.Fields = new PropertySet(propertyDefinitionBase);

                // Get the list of items (this includes attachments if the Attachment field was selected for output).
                List <OItem> oItems = email.GetItems(nRecordLimit);

                // We will need to send status updates to Alteryx at regular intervals during
                // this process, so we'll do that based on an elapsed time.
                DateTime last = DateTime.Now;

                // We need to keep track of how many records we have processed.
                long nRecords = 0;

                // Process the data in each message object.
                foreach (var oItem in oItems)
                {
                    // If we've exceeded the record limit, stop processing.
                    if (nRecords >= nRecordLimit)
                    {
                        break;
                    }

                    // Reset our output record so we can reuse it.  This is better than
                    // creating a new Record in each iteration as these objects can get large.
                    recordOut.Reset();

                    // For each field, load the data from the corresponding element into the Record.
                    foreach (XmlInputField field in xmlConfig.Fields)
                    {
                        // Get the FieldBase from the RecordInfo for the field.
                        AlteryxRecordInfoNet.FieldBase fieldBase = recordInfoOut.GetFieldByName(field.Name, false);
                        if (fieldBase != null)
                        {
                            // Find the element within the container element that has the same name as the field.
                            var value = Convert.ToString(oItem.Item.GetType().GetProperty(field.Name).GetValue(oItem.Item, null));

                            if (value == null)
                            {
                                // If the field element doesn't exist, set the output field's value to null.
                                fieldBase.SetNull(recordOut);
                            }
                            else
                            {
                                // Otherwise, set the output field's value based on the element's inner text.
                                fieldBase.SetFromString(recordOut, value);
                            }
                        }
                    }

                    // Return message attachments if applicable.
                    if (!string.IsNullOrWhiteSpace(xmlConfig.AttachmentPath))
                    {
                        foreach (var attachment in oItem.Attachments)
                        {
                            // Reset our output record so we can reuse it.  This is better than
                            // creating a new Record in each iteration as these objects can get large.
                            recordOut_AttachmentPaths.Reset();

                            // Get the FieldBase from the RecordInfo for the ID field.
                            AlteryxRecordInfoNet.FieldBase fieldBase_ID = recordInfoOut_AttachmentPaths.GetFieldByName("ID", false);
                            if (fieldBase_ID != null)
                            {
                                fieldBase_ID.SetFromString(recordOut_AttachmentPaths, oItem.Item.Id.ToString());
                            }

                            // Get the FieldBase from the RecordInfo for the AttachmentPath field.
                            AlteryxRecordInfoNet.FieldBase fieldBase_AttachmentPath = recordInfoOut_AttachmentPaths.GetFieldByName("AttachmentPath", false);
                            if (fieldBase_AttachmentPath != null)
                            {
                                fieldBase_AttachmentPath.SetFromString(recordOut_AttachmentPaths, attachment.AttachmentPath);
                            }

                            // Send the record to the downstream tools through the PluginOutputConnectionHelper.
                            m_attachmentOutputHelper.PushRecord(recordOut_AttachmentPaths.GetRecord());
                        }
                    }

                    // Send the record to the downstream tools through the PluginOutputConnectionHelper.
                    m_outputHelper.PushRecord(recordOut.GetRecord());

                    // If at least 1 second has passed since we started or our last update, update progress.
                    if (DateTime.Now.Subtract(last).TotalSeconds >= 1)
                    {
                        // Determine the percent complete:  (Records Processed) / Min(RecordLimit, # of Container Elements)
                        double percentComplete = (double)nRecords / Math.Min(nRecordLimit, oItems.Count);

                        // Output the progress
                        if (m_engineInterface.OutputToolProgress(m_nToolId, percentComplete) != 0)
                        {
                            // If this returns anything but 0, then the user has canceled the operation.
                            throw new AlteryxRecordInfoNet.UserCanceledException();
                        }

                        // Have the PluginOutputConnectionHelper ask the downstream tools to update their progress.
                        m_outputHelper.UpdateProgress(percentComplete);

                        // Reset the timer.
                        last = DateTime.Now;
                    }

                    // Have the PluginOutputConnectionHelper update the record count display in Alteryx.
                    // The PluginOutputConnectionHelper will actually only do this if enough time and data has elapsed,
                    // so it's ok to call this in every iteration.
                    m_outputHelper.OutputRecordCount(false);

                    // Update our record count.
                    nRecords++;
                }

                // If we weren't just getting the output config, send a status message to Alterys that
                // will display the number of records that we output.
                if (nRecordLimit > 0)
                {
                    m_engineInterface.OutputMessage(m_nToolId, AlteryxRecordInfoNet.MessageStatus.STATUS_Info, nRecords.ToString() + " records read from " + xmlConfig.UserName);
                }


                // Tell Alteryx that we are done sending data so that it can close the connections to our plugin.
                m_engineInterface.OutputMessage(m_nToolId, AlteryxRecordInfoNet.MessageStatus.STATUS_Complete, "");
            }

            // Close our ouput connections.
            m_outputHelper.Close();
            m_attachmentOutputHelper.Close();

            // Return true to indicate that we successfully processed our data.
            return(true);
        }