public Dictionary<string, PDFField> GetPDFFormFields(PDDocument document, bool includeValues)
        {
            Dictionary<string, PDFField> pdfFormFields = new Dictionary<string, PDFField>();

            PDDocumentCatalog docCat = document.getDocumentCatalog();
            PDAcroForm form = docCat.getAcroForm();

            string aa = string.Empty;
            var a = form.getFields();

            var iterator = a.iterator();

            while (iterator.hasNext())
            {
                try
                {
                    PDFField pdffield = new PDFField();

                    PDField f = (PDField)iterator.next();

                    pdffield.Type = f.getFieldType();
                    pdffield.IsRequired = f.isRequired();
                    pdffield.IsReadOnly = f.isReadonly();
                    pdffield.FullName = f.getFullyQualifiedName();
                    pdffield.AlternativeName = f.getAlternateFieldName();
                    pdffield.PartialName = f.getPartialName();

                    string fieldvalue = string.Empty;

                    // sig field throws not implemented in ver 1.2.1
                    if (includeValues)
                    {
                        try
                        {
                            fieldvalue = f.getValue();
                        }
                        catch (Exception e) { }

                    }

                    if (pdffield.Type == "Sig")
                    {
                        PDSignatureField sig = (PDSignatureField)f;
                        var x = sig.getSignature();
                        if (x != null)
                        {
                            fieldvalue = x.getName();
                        }
                    }

                    pdffield.FieldValue = fieldvalue;

                    pdfFormFields.Add(pdffield.FullName, pdffield);
                }
                catch (Exception e) { }
            }

            return pdfFormFields;
        }
        /// <summary>
        /// Executes the Service Object method and returns any data.
        /// </summary>
        /// <param name="inputs">A Property[] array containing all the allowed input properties.</param>
        /// <param name="required">A RequiredProperties collection containing the required properties.</param>
        /// <param name="returns">A Property[] array containing all the allowed return properties.</param>
        /// <param name="methodType">A MethoType indicating what type of Service Object method was called.</param>
        /// <param name="serviceObject">A ServiceObject containing populated properties for use with the method call.</param>
        public void Execute(Property[] inputs, RequiredProperties required, Property[] returns, MethodType methodType, ServiceObject serviceObject)
        {
            #region Get All Field Values

            if (serviceObject.Methods[0].Name.Equals("getallfieldvalues"))
            {
                serviceObject.Properties.InitResultTable();

                // get input field value
                string pdfuri = inputs.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value.ToString();

                PDFInfo info = new PDFInfo();
                Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

                try
                {
                    PDDocument doc = Utilities.Utils.GetPDDocument(pdfUri);
                    info = GetPDFDoucmentInformation(doc);
                    fields = GetPDFFormFields(doc, true);
                    doc.close();
                    doc = null;
                }
                catch(Exception ex)
                {
                    throw new Exception(string.Format("Error retrieving PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
                }

                returns.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value = pdfuri;

                foreach(Property prop in returns)
                {
                    PDFField fieldvalue = new PDFField();

                    string fullname = string.Empty;

                    object pfn = prop.MetaData.ServiceProperties["pdffullname"];
                    if (pfn == null)
                    {
                        fullname = prop.Name;
                    }
                    else
                    {
                        fullname = pfn.ToString();
                    }

                    if (fields.TryGetValue(fullname, out fieldvalue))
                    {
                        prop.Value = fieldvalue.FieldValue;
                    }
                }

                Type type = typeof(PDFInfo);
                PropertyInfo[] props = type.GetProperties();
                foreach (var p in props)
                {
                    object v = info.GetType().GetProperty(p.Name).GetValue(info, null);
                    if (v != null)
                    {
                        string value = v.ToString();
                        returns.Where(q => q.Name.Equals(p.Name)).First().Value = value;
                    }
                }

                serviceObject.Properties.BindPropertiesToResultTable();

            }

            #endregion Get All Field Values

            #region Contains Signatures

            if (serviceObject.Methods[0].Name.Equals("containssignatures"))
            {
                serviceObject.Properties.InitResultTable();

                // get input field value
                string pdfuri = inputs.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value.ToString();

                PDFInfo info = new PDFInfo();
                Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

                bool containssigs = false;

                try
                {
                    PDDocument doc = Utilities.Utils.GetPDDocument(pdfUri);
                    fields = GetPDFFormFields(doc, true);
                    doc.close();
                    doc = null;
                    containssigs = ContainsSignatures(fields);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error retrieving PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
                }

                returns.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value = pdfuri;
                returns.Where(p => p.Name.Equals("containssignatures")).FirstOrDefault().Value = containssigs;

                serviceObject.Properties.BindPropertiesToResultTable();

            }

            #endregion Contains Signatures

            // not implemented with PDFBox
            #region Contains Unsigned Signatures

            //if (serviceObject.Methods[0].Name.Equals("containsunsignedsignatures"))
            //{
            //    serviceObject.Properties.InitResultTable();

            //    // get input field value
            //    string pdfuri = inputs.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value.ToString();

            //    PDFInfo info = new PDFInfo();
            //    Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

            //    bool containsunsignedsigs = false;

            //    try
            //    {
            //        throw new Exception("Not implemented");
            //    }
            //    catch (Exception ex)
            //    {
            //        throw new Exception(string.Format("Error retrieving PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
            //    }

            //    returns.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value = pdfuri;
            //    returns.Where(p => p.Name.Equals("containsunsignedsignatures")).FirstOrDefault().Value = containsunsignedsigs;

            //    serviceObject.Properties.BindPropertiesToResultTable();

            //}

            #endregion Contains Signatures

            #region Update PDF Field

            if (serviceObject.Methods[0].Name.Equals("updatepdffields"))
            {
                serviceObject.Properties.InitResultTable();

                // get input field value
                string pdfuri = inputs.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value.ToString();
                bool base64 = false;
                string base64temp = inputs.Where(p => p.Name.Equals("returnbase64")).FirstOrDefault().Value.ToString();
                bool.TryParse(base64temp, out base64);

                string workingFolder = serviceBroker.Service.ServiceConfiguration["WorkingFolder"].ToString();
                if (workingFolder.LastIndexOf(@"\") != workingFolder.Length - 1)
                {
                    workingFolder += @"\";
                }
                string filename = Guid.NewGuid().ToString() + ".pdf";
                string workingPath = workingFolder + filename;

                PDFInfo info = new PDFInfo();
                Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

                Dictionary<string, string> updates = new Dictionary<string, string>();
                foreach (Property prop in inputs)
                {
                    object pfn = prop.MetaData.ServiceProperties["pdffullname"];
                    if (!prop.Name.Equals("pdfuri") && pfn != null)
                    {
                        if (prop.Value != null)
                        {
                            updates.Add(pfn.ToString(), prop.Value.ToString());
                        }
                    }
                }

                if (updates.Count > 0)
                {
                    // call update method
                    try
                    {
                        PDDocument doc = Utilities.Utils.GetPDDocument(pdfUri);
                        PDDocumentCatalog documentCatalog = doc.getDocumentCatalog();
                        PDAcroForm acroForm = documentCatalog.getAcroForm();
                        foreach (KeyValuePair<string, string> val in updates)
                        {
                            PDField field = acroForm.getField(val.Key);
                            if (field != null)
                            {
                                field.setValue(val.Value);
                            }
                        }
                        doc.save(workingPath);
                        doc.close();
                        doc = null;
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(string.Format("Error updateing PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
                    }

                    returns.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value = pdfuri;
                    returns.Where(p => p.Name.Equals("returnpath")).FirstOrDefault().Value = workingPath;
                    returns.Where(p => p.Name.Equals("returnbase64")).FirstOrDefault().Value = base64;

                    // read created doc
                    try
                    {
                        PDDocument doc = Utilities.Utils.GetPDDocument(workingPath);
                        info = GetPDFDoucmentInformation(doc);
                        fields = GetPDFFormFields(doc, true);
                        doc.close();
                        doc = null;
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(string.Format("Error retrieving PDF document from {0}. Exception: {1}", workingPath, ex.Message));
                    }

                    foreach (Property prop in returns)
                    {
                        PDFField fieldvalue = new PDFField();

                        string fullname = string.Empty;

                        object pfn = prop.MetaData.ServiceProperties["pdffullname"];
                        if (pfn == null)
                        {
                            fullname = prop.Name;
                        }
                        else
                        {
                            fullname = pfn.ToString();
                        }

                        if (fields.TryGetValue(fullname, out fieldvalue))
                        {
                            prop.Value = fieldvalue.FieldValue;
                        }
                    }

                    Type type = typeof(PDFInfo);
                    PropertyInfo[] props = type.GetProperties();
                    foreach (var p in props)
                    {
                        object v = info.GetType().GetProperty(p.Name).GetValue(info, null);
                        if (v != null)
                        {
                            string value = v.ToString();
                            returns.Where(q => q.Name.Equals(p.Name)).First().Value = value;
                        }
                    }

                    // get base64 of file
                    if (base64)
                    {
                        FileStream fs = new FileStream(workingPath, FileMode.Open, FileAccess.Read);
                        byte[] filebytes = new byte[fs.Length];
                        fs.Read(filebytes, 0, Convert.ToInt32(fs.Length));
                        string encodedData = Convert.ToBase64String(filebytes);
                        returns.Where(p => p.Name.Equals("base64pdf")).FirstOrDefault().Value = encodedData;
                    }

                    serviceObject.Properties.BindPropertiesToResultTable();
                    return;
                }
            }

            #endregion Update PDF Field

            #region Generate Create Table SQL

            if (serviceObject.Methods[0].Name.Equals("generatecreatetablesql"))
            {
                serviceObject.Properties.InitResultTable();

                string pdfuri = serviceBroker.Service.ServiceConfiguration["pdfUri"].ToString();

                PDFInfo info = new PDFInfo();
                Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

                string sql = string.Empty;

                // read created doc
                try
                {
                    PDDocument doc = Utilities.Utils.GetPDDocument(pdfUri);
                    info = GetPDFDoucmentInformation(doc);
                    fields = GetPDFFormFields(doc, true);

                    sql = GenerateCreateTableSQL(info, fields);

                    doc.close();
                    doc = null;
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error generating create table SQL from {0}. Exception: {1}", pdfuri, ex.Message));
                }

                returns.Where(p => p.Name.Equals("generatedsql")).FirstOrDefault().Value = sql;

                serviceObject.Properties.BindPropertiesToResultTable();

            }

            #endregion Generate Create Table SQL

            #region Copy Form Data to SmartObject

            if (serviceObject.Methods[0].Name.Equals("copyformdatatosmartobject"))
            {
                serviceObject.Properties.InitResultTable();

                string pdfuri = inputs.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value.ToString();
                string smoname = inputs.Where(p => p.Name.Equals("formstoresmartobjectname")).FirstOrDefault().Value.ToString();
                string smometh = inputs.Where(p => p.Name.Equals("formstoremethodname")).FirstOrDefault().Value.ToString();
                string returnprop = inputs.Where(p => p.Name.Equals("returnidpropertyname")).FirstOrDefault().Value.ToString();

                string returnvalue = string.Empty;

                PDFInfo info = new PDFInfo();
                Dictionary<string, PDFField> fields = new Dictionary<string, PDFField>();

                try
                {
                    PDDocument doc = Utilities.Utils.GetPDDocument(pdfUri);
                    info = GetPDFDoucmentInformation(doc);
                    fields = GetPDFFormFields(doc, true);
                    doc.close();
                    doc = null;
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error retrieving PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
                }

                string returnId = string.Empty;
                try
                {
                    returnId = Utilities.SmartObjectUtils.CreateDataFromPDFForm(smoname, smometh, returnprop, info, fields);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error updated SmartObject from PDF document from {0}. Exception: {1}", pdfuri, ex.Message));
                }

                returns.Where(p => p.Name.Equals("pdfuri")).FirstOrDefault().Value = pdfuri;
                returns.Where(p => p.Name.Equals("formstoresmartobjectname")).FirstOrDefault().Value = smoname;
                returns.Where(p => p.Name.Equals("formstoremethodname")).FirstOrDefault().Value = smometh;
                returns.Where(p => p.Name.Equals("returnidpropertyname")).FirstOrDefault().Value = returnprop;
                returns.Where(p => p.Name.Equals("returnid")).FirstOrDefault().Value = returnId;

                serviceObject.Properties.BindPropertiesToResultTable();

            }

            #endregion Copy Form Data to SmartObject
        }