public Schema GetSchema(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters)
        {
            Schema schema = Schema.Create();

            Microsoft.MetadirectoryServices.SchemaType type;

            //we want to fetch schema for all MAs, that way configuration wont get lost if an item is
            //unselected, and the checkbox can become simply an activate/deactivate switch
            DataSet mas = FIMConfiguration.GetManagementAgents(null);

            foreach (DataRow ma in mas.Tables["Config"].Rows)
            {
                string maName = ma["ma_name"].ToString();
                string maType = ma["ma_type"].ToString();
                string maList = ma["ma_listname"].ToString();

                if (maType.Equals("FIM", StringComparison.InvariantCultureIgnoreCase) ||
                    maList.Equals("Provisioning Management Agent (Insight)", StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                //create a new schema type based on the ma
                type = Microsoft.MetadirectoryServices.SchemaType.Create(maName, false);

                //add a generic Anchor Attribute to allow user to add flows for the actual anchor
                type.Attributes.Add(SchemaAttribute.CreateAnchorAttribute("Anchor", AttributeType.String));

                //we must preface each attribute with the MA name to make it unique across the schema allowing for
                //an attribute in two different MAs with different data types, etc.

                //our data will come back as XML data, we will need to parse it for what we need
                XmlDocument xmldoc = FIMConfiguration.GetConfigXML(maName, "ma_schema_xml");

                XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(xmldoc.NameTable);
                xmlnsManager.AddNamespace("dsml", "http://www.dsml.org/DSML");
                xmlnsManager.AddNamespace("ms-dsml", "http://www.microsoft.com/MMS/DSML");

                XmlNodeList attributes = xmldoc.SelectNodes("//dsml:directory-schema/dsml:attribute-type", xmlnsManager);

                //add each attribute found to the schema
                foreach (XmlNode attrib in attributes)
                {
                    string oid = attrib.SelectSingleNode("./dsml:syntax", xmlnsManager).InnerText;
                    type.Attributes.Add(SchemaAttribute.CreateSingleValuedAttribute(maName + " - " + attrib.Attributes["id"].Value, FIMConfiguration.GetDataType(oid)));
                }

                schema.Types.Add(type);
            }

            return(schema);
        }
        void IMVSynchronization.Provision(MVEntry mventry)
        {
            //get our provisioning ma from the db
            string provisioningMAName = FIMConfiguration.GetProvisioningMA()["ma_name"].ToString();

            XmlDocument xmldoc     = FIMConfiguration.GetConfigXML(provisioningMAName, "private_configuration_xml");
            XmlNodeList attributes = xmldoc.SelectNodes("//MAConfig/parameter-values/parameter");

            //loop through each MA/object type selected
            foreach (XmlNode attrib in attributes)
            {
                string param      = attrib.Attributes["name"].Value;
                string maName     = param.Substring(0, param.LastIndexOf(" - "));
                string objectType = param.Substring(param.LastIndexOf(" - ") + 3);

                //if enabled, provision it
                if (attrib.InnerText.Equals("1"))
                {
                    //our ma has been enabled for provisioning, create a new csentry and add initial flows
                    ConnectedMA ma = mventry.ConnectedMAs[maName];

                    if (ma.Connectors.Count == 0)
                    {
                        CSEntry csentry = ma.Connectors.StartNewConnector(objectType);

                        //go and get the real anchor info, our provisioning ma
                        //uses a generic anchor to ensure tha flows can be
                        //defined for the actual anchor
                        XmlDocument maSchemaConfig = FIMConfiguration.GetConfigXML(maName, "dn_construction_xml");
                        XmlNode     maSchemaRoot   = maSchemaConfig.FirstChild;

                        //get dn for the object
                        List <string> anchors = new List <string>();
                        if (maSchemaRoot.FirstChild.Name.Equals("attribute", StringComparison.InvariantCultureIgnoreCase))
                        {
                            XmlNodeList anchorList = maSchemaConfig.SelectNodes("//dn-construction/attribute");

                            foreach (XmlNode anchor in anchorList)
                            {
                                anchors.Add(anchor.InnerText);
                            }
                        }
                        else
                        {
                            XmlNodeList anchorList = maSchemaConfig.SelectNodes("//dn-construction/dn[@object-type='" + objectType + "']/attribute");

                            foreach (XmlNode anchor in anchorList)
                            {
                                anchors.Add(anchor.InnerText);
                            }
                        }

                        //our export schema defines the initial attributes to flow
                        XmlDocument xmlFlows = FIMConfiguration.GetConfigXML(provisioningMAName, "export_attribute_flow_xml");
                        XmlNodeList flows    = xmlFlows.SelectNodes("//export-attribute-flow/export-flow-set[@cd-object-type='" + maName + "']/export-flow");

                        foreach (XmlNode flow in flows)
                        {
                            //get the mapping for each flow defined and provision an initial flow
                            string csAttribName = flow.Attributes["cd-attribute"].Value;
                            csAttribName = csAttribName.Substring(csAttribName.LastIndexOf(" - ") + 3);

                            XmlNode         mappingNode = flow.FirstChild;
                            string          mappingType = mappingNode.Name;
                            string          flowValue   = null;
                            ValueCollection flowValues  = null;

                            switch (mappingType)
                            {
                            case "direct-mapping":

                                string mvAttribName = mappingNode.FirstChild.InnerText;

                                if (mventry[mvAttribName].IsPresent)
                                {
                                    if (mventry[mvAttribName].IsMultivalued)
                                    {
                                        flowValues = mventry[mvAttribName].Values;
                                    }
                                    else
                                    {
                                        //TODO: convert this to its proper type if necessary (i.e. int, boolean, etc)
                                        flowValue = mventry[mvAttribName].Value;
                                    }
                                }
                                break;

                            case "constant-mapping":
                                flowValue = mappingNode.FirstChild.InnerText;
                                break;

                            case "scripted-mapping":
                                break;

                            default:
                                throw new Exception("Unexpected mapping type encountered. Only Direct, Constant and Advanced/Scripted flows are allowed. Check flow rules and try again.");
                            }

                            if (flowValue != null || flowValues != null)
                            {
                                //calc dn if necessary
                                if (csAttribName.Equals("dn", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    //are we safe to assume that if we are calculating dn, we must
                                    //be using flowValue and not flowValues?
                                    string         rdn = flowValue.ToString();
                                    ReferenceValue dn  = ma.EscapeDNComponent(rdn);
                                    csentry.DN = dn;
                                }
                                else
                                {
                                    try
                                    {
                                        if (flowValue != null)
                                        {
                                            csentry[csAttribName].Values.Add(flowValue);
                                        }
                                        else if (flowValues != null)
                                        {
                                            csentry[csAttribName].Values.Add(flowValues);
                                        }
                                    }
                                    catch (InvalidOperationException ex)
                                    {
                                        if (!ex.Message.Equals("attribute " + csAttribName + " is read-only", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            throw;
                                        }
                                        else
                                        {
                                            //our anchor attribute is read only, set a temporary dn
                                            if (anchors.Contains(csAttribName))
                                            {
                                                ReferenceValue dn = ma.EscapeDNComponent(Guid.NewGuid().ToString());
                                                csentry.DN = dn;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        //do we want to throw an error now if any writeable anchor attributes have not been set??
                        //otherwise they will get one on export, we will leave it that way for now

                        csentry.CommitNewConnector();
                    }
                }
            }
        }
        public System.Collections.Generic.IList <ConfigParameterDefinition> GetConfigParameters(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters, ConfigParameterPage page)
        {
            List <ConfigParameterDefinition> configParametersDefinitions = new List <ConfigParameterDefinition>();

            switch (page)
            {
            case ConfigParameterPage.Connectivity:
                //we have to configure the MAs being seletected in the Connectivity page so that the information
                //will be available to us when fetching the schema for the items selected
                configParametersDefinitions.Add(ConfigParameterDefinition.CreateLabelParameter("Enable provisioning for the following types:"));

                //look up MAs and list them as check boxes for provisioning enablement
                DataSet mas = FIMConfiguration.GetManagementAgents(null);

                foreach (DataRow ma in mas.Tables["Config"].Rows)
                {
                    string maName = ma["ma_name"].ToString();
                    string maType = ma["ma_type"].ToString();
                    string maList = ma["ma_listname"].ToString();

                    if (maType.Equals("FIM", StringComparison.InvariantCultureIgnoreCase) ||
                        maList.Equals("Provisioning Management Agent (Insight)", StringComparison.InvariantCultureIgnoreCase))
                    {
                        continue;
                    }

                    //our data will come back as XML data, we will need to parse it for what we need
                    XmlDocument xmldoc = FIMConfiguration.GetConfigXML(maName, "ma_schema_xml");

                    XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(xmldoc.NameTable);
                    xmlnsManager.AddNamespace("dsml", "http://www.dsml.org/DSML");
                    xmlnsManager.AddNamespace("ms-dsml", "http://www.microsoft.com/MMS/DSML");

                    //TODO:  what happens when a sql column defines the object type?
                    XmlNodeList objectTypes = xmldoc.SelectNodes("//dsml:directory-schema/dsml:class", xmlnsManager);

                    foreach (XmlNode ot in objectTypes)
                    {
                        //add the object type as a selection
                        ConfigParameterDefinition conf = ConfigParameterDefinition.CreateCheckBoxParameter(maName + " - " + ot.Attributes["id"].Value.Replace(" - ", " _ "));
                        configParametersDefinitions.Add(conf);
                    }

                    //TODO:  what happens to the UI when we have a alot of entries?
                    configParametersDefinitions.Add(ConfigParameterDefinition.CreateDividerParameter());
                }

                break;

            case ConfigParameterPage.Global:
                break;

            case ConfigParameterPage.Partition:
                break;

            case ConfigParameterPage.RunStep:
                break;
            }

            return(configParametersDefinitions);
        }