Src/Offering.cs

#if ( _SERVICEMANAGER_R2_ )
using System;
using System.Linq;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement.Configuration.IO;
using Microsoft.EnterpriseManagement.ConnectorFramework;
using System.Text.RegularExpressions;
 
namespace SMLets
{
    [Cmdlet(VerbsCommon.Get, "SCSMRequestOffering", DefaultParameterSetName = "NAME")]
    public class GetSCSMRequestOfferingCommand : GetSCSMROSO
    {
        public override void SetClassType(ManagementPackClass c)
        {
            base.SetClassType(c);
        }
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            SetClassType(SMHelpers.GetManagementPackClass("System.RequestOffering", SMHelpers.GetManagementPack("System.ServiceCatalog.Library", _mg)));
            SetProjectionType(SMHelpers.GetManagementPackTypeProjection("System.RequestOffering.ProjectionType", SMHelpers.GetManagementPack("ServiceManager.ServiceCatalog.Library", _mg)));
        }
    }
    [Cmdlet(VerbsCommon.Get, "SCSMServiceOffering", DefaultParameterSetName = "NAME")]
    public class GetSCSMServiceOfferingCommand : GetSCSMROSO
    {
        public override void SetClassType(ManagementPackClass c)
        {
            base.SetClassType(c);
        }
        
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            SetClassType(SMHelpers.GetManagementPackClass("System.ServiceOffering", SMHelpers.GetManagementPack("System.ServiceCatalog.Library", _mg)));
            SetProjectionType(SMHelpers.GetManagementPackTypeProjection("System.ServiceOffering.ProjectionType", SMHelpers.GetManagementPack("ServiceManager.ServiceCatalog.Library", _mg)));
        }
    }
 
    public class GetSCSMROSO : ObjectCmdletHelper
    {
 
        private string[] _name = {"*"};
        [Parameter(Position = 0, ParameterSetName = "NAME",ValueFromPipeline=true)]
        public string[] Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string[] _displayName;
        [Parameter(ParameterSetName = "DISPLAYNAME")]
        public string[] DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }
        private string[] _id;
        [Parameter(Position=0,ParameterSetName = "ID", ValueFromPipeline = true)]
        public string[] Id
        {
            get { return _id; }
            set { _id = value; }
        }
        private SwitchParameter _published;
        [Parameter]
        public SwitchParameter Published
        {
            get { return _published; }
            set { _published = value; }
        }
 
        Object[] myParamVals;
        private ManagementPackClass ROSOclass;
        private ManagementPackTypeProjection ROSOprojection;
        public virtual void SetClassType(ManagementPackClass c)
        {
            ROSOclass = c;
        }
        public virtual void SetProjectionType(ManagementPackTypeProjection p)
        {
            ROSOprojection = p;
        }
        private List<string> filters;
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            filters = new List<string>();
        }
 
 
 
        protected override void ProcessRecord()
        {
            string myProperty = "NAME";
            switch (ParameterSetName)
            {
                case "NAME":
                    {
                        myParamVals = Name;
                        myProperty = "Name";
                        break;
                    }
                case "DISPLAYNAME":
                    {
                        myParamVals = DisplayName;
                        myProperty = "DisplayName";
                        break;
                    }
                case "ID":
                    {
                        myParamVals = Id;
                        myProperty = "Id";
                        break;
                    }
                default:
                    {
                    ThrowTerminatingError(new ErrorRecord(new ArgumentException("unknown parameter set"), "bad parameter set", ErrorCategory.InvalidArgument, ParameterSetName));
                    break;
                }
            }
            string OPERATOR = "=";
            foreach (string s in myParamVals)
            {
                string myS = s.Replace("*", "%");
                WriteVerbose(s + " => " + myS);
                if (myS.IndexOf("%") > -1)
                {
                    OPERATOR = "LIKE";
                }
                filters.Add(String.Format("{0} {1} '{2}'", myProperty, OPERATOR, myS));
            }
        }
        protected override void EndProcessing()
        {
            base.EndProcessing();
            string combinedFilter = String.Join(" OR ", filters.ToArray<string>());
            WriteVerbose(combinedFilter);
            try
            {
                EnterpriseManagementObjectGenericCriteria myc = new EnterpriseManagementObjectGenericCriteria(combinedFilter);
 
                foreach (EnterpriseManagementObject o in _mg.EntityObjects.GetObjectReader<EnterpriseManagementObject>(myc, ROSOclass, ObjectQueryOptions.Default))
                {
                    // This should really be done as criteria, but I don't want to change the way that I use generic criteria above
                    if ( Published)
                    {
                        try // if things fall over, just keep going
                        {
                            if (o[null, "Status"].Value.ToString() != "System.Offering.StatusEnum.Published")
                            {
                                continue;
                            }
                        }
                        catch
                        {
                            ;
                        }
                    }
                    string pcr = String.Format("ID -eq '{0}'", o[null, "ID"].Value.ToString());
                    WriteVerbose(pcr);
                    String pcc = ConvertFilterToCriteriaString(o.GetLeastDerivedNonAbstractClass(), pcr, true);
                    WriteVerbose(":" + pcc + ":");
                    ObjectProjectionCriteria pc = new ObjectProjectionCriteria(pcc ,ROSOprojection,_mg);
 
                    foreach (EnterpriseManagementObjectProjection p in _mg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(pc, ObjectQueryOptions.Default))
                    {
                        WriteObject(ServiceManagerObjectHelper.AdaptProjection(this, p, ROSOprojection.Name));
                        // WriteObject(ServiceManagerObjectHelper.AdaptManagementObject(o));
                    }
                }
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(e, "bad generic criteria", ErrorCategory.InvalidArgument, combinedFilter));
            }
        }
    }
    [Cmdlet(VerbsCommon.Remove, "SCSMRequestOffering", SupportsShouldProcess = true)]
    public class RemoveSCSMRequestOfferingCommand : RemoveOffering
    {
        protected override void SetObjectClassName(string name)
        {
            base.SetObjectClassName("System.RequestOffering");
        }
         
    }
 
    [Cmdlet(VerbsCommon.Remove, "SCSMServiceOffering", SupportsShouldProcess = true)]
    public class RemoveSCSMServiceOfferingCommand : RemoveOffering
    {
        protected override void SetObjectClassName(string name)
        {
            base.SetObjectClassName("System.ServiceOffering");
        }
    }
 
 
    public class RemoveOffering : ObjectCmdletHelper
    {
        private EnterpriseManagementObjectProjection[] _projection;
        [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true)]
        public EnterpriseManagementObjectProjection[] Projection
        {
            get { return _projection; }
            set { _projection = value; }
        }
        private string _objectClassName = "System.ServiceOffering";
        protected virtual void SetObjectClassName(string name)
        {
            _objectClassName = name;
        }
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            foreach (EnterpriseManagementObjectProjection p in Projection)
            {
                if (String.Compare(p.Object.GetLeastDerivedNonAbstractClass().Name, _objectClassName, true) == 0)
                {
                    WriteError(new ErrorRecord(
                        new ArgumentException("Invalid Projection Type"),
                        "ProjectionNotServiceOffering", ErrorCategory.InvalidArgument, p));
                }
                else
                {
                    if (ShouldProcess(p.Object.DisplayName))
                    {
                        p.Remove();
                        p.Overwrite();
                    }
                }
            }
        }
    }
    [Cmdlet(VerbsCommon.Add, "SCSMRequestOffering", SupportsShouldProcess = true)]
    public class AddSCSMRequestOfferingCommand : PSCmdlet
    {
        #region privates
        private EnterpriseManagementObject[] _requestOffering;
        private EnterpriseManagementObjectProjection[] _serviceOffering;
        private ManagementPackRelationship RelatesToRequestOffering;
        private IncrementalDiscoveryData idd;
        #endregion
        #region parameters
        [Parameter(Position=0,Mandatory=true)]
        public EnterpriseManagementObject[] RequestOffering
        {
            get { return _requestOffering; }
            set { _requestOffering = value; }
        }
        [Parameter(Position = 1, Mandatory = true)]
        public EnterpriseManagementObjectProjection[] ServiceOffering
        {
            get { return _serviceOffering; }
            set { _serviceOffering = value; }
        }
        #endregion
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            RelatesToRequestOffering = RequestOffering[0].ManagementGroup.EntityTypes.GetRelationshipClasses(new ManagementPackRelationshipCriteria("Name = 'System.ServiceOfferingRelatesToRequestOffering'")).First();
            idd = new IncrementalDiscoveryData();
        }
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            foreach (EnterpriseManagementObjectProjection p in ServiceOffering)
            {
                foreach (EnterpriseManagementObject e in RequestOffering)
                {
                    if (ShouldProcess(p.Object.DisplayName))
                    {
                        p.Add(e, RelatesToRequestOffering.Target);
                        idd.Add(p);
                    }
                }
            }
        }
        protected override void EndProcessing()
        {
            base.EndProcessing();
            if (ShouldProcess("Save All Changes"))
            {
                idd.Commit(RequestOffering[0].ManagementGroup);
            }
        }
    }
    [Cmdlet(VerbsCommon.New, "SCSMRequestOffering", SupportsShouldProcess = true)]
    public class NewSCSMRequestOfferingCommand : ObjectCmdletHelper
    {
        #region privates
        private String _briefDescription;
        private String _comment;
        private String _displayName;
        private String _estimatedTimeToCompletion;
        private Stream _image;
        private String _notes;
        private String _overview;
        private ROMapElement[] _presentationMappingTemplate;
        private DateTime ? _publishDate;
        private string _status;
        private ManagementPackObjectTemplate _targetTemplate;
        private ManagementPack _managementPack;
        private EnterpriseManagementObject[] _relatedKnowledgeArticle;
        private EnterpriseManagementObject _publishedBy;
        private EnterpriseManagementObject _owner;
        private SwitchParameter _passThru;
        private ManagementPackClass _roClass;
        private ManagementPackTypeProjection _roProjection;
        private SwitchParameter _noCommit;
        #endregion
 
        #region parameters
        [Parameter]
        public String BriefDescription
        {
            get { return _briefDescription; }
            set { _briefDescription = value; }
        }
        [Parameter]
        public String Comment
        {
            get { return _comment; }
            set { _comment = value; }
        }
        [Parameter]
        public String DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }
        [Parameter]
        public String EstimatedTimeToCompletion
        {
            get { return _estimatedTimeToCompletion; }
            set { _estimatedTimeToCompletion = value; }
        }
        [Parameter]
        public Stream Image
        {
            get { return _image; }
            set { _image = value; }
        }
        [Parameter]
        public String Notes
        {
            get { return _notes; }
            set { _notes = value; }
        }
        [Parameter]
        public String Overview
        {
            get { return _overview; }
            set { _overview = value; }
        }
        [Parameter]
        public ROMapElement[] Questions
        {
            get { return _presentationMappingTemplate; }
            set { _presentationMappingTemplate = value; }
        }
        [Parameter]
        public DateTime ? PublishDate
        {
            get { return _publishDate; }
            set { _publishDate = value; }
        }
        [Parameter]
        public string Status
        {
            get { return _status; }
            set { _status = value; }
        }
        [Parameter]
        public ManagementPackObjectTemplate TargetTemplate
        {
            get { return _targetTemplate; }
            set { _targetTemplate = value; }
        }
        private String _title;
        [Parameter(Mandatory = true)]
        public String Title
        {
            get { return _title; }
            set { _title = value; }
        }
        [Parameter(Mandatory = true)]
        public ManagementPack ManagementPack
        {
            get { return _managementPack; }
            set { _managementPack = value; }
        }
        [Parameter]
        public EnterpriseManagementObject[] RelatedKnowledgeArticle
        {
            get { return _relatedKnowledgeArticle; }
            set { _relatedKnowledgeArticle = value; }
        }
        [Parameter]
        public EnterpriseManagementObject PublishedBy
        {
            get { return _publishedBy; }
            set { _publishedBy = value; }
        }
        [Parameter]
        public EnterpriseManagementObject Owner
        {
            get { return _owner; }
            set { _owner = value; }
        }
        [Parameter]
        public SwitchParameter PassThru
        {
            get { return _passThru; }
            set { _passThru = value; }
        }
        [Parameter]
        public SwitchParameter NoCommit
        {
            get { return _noCommit; }
            set { _noCommit = value; }
        }
        #endregion
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
            _roClass = SMHelpers.GetManagementPackClass("System.RequestOffering", SMHelpers.GetManagementPack("System.ServiceCatalog.Library", _mg));
            _roProjection = SMHelpers.GetManagementPackTypeProjection("System.RequestOffering.ProjectionType", SMHelpers.GetManagementPack("ServiceManager.ServiceCatalog.Library", _mg));
        }
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            if (TargetTemplate == null)
            {
                TargetTemplate = _mg.Templates.GetObjectTemplates(new ManagementPackObjectTemplateCriteria("Name = 'ServiceManager.ServiceRequest.Library.Template.DefaultServiceRequest'")).First();
            }
            EnterpriseManagementObjectProjection junk = new EnterpriseManagementObjectProjection(_mg, TargetTemplate);
            IEnumerable<string> propertynames = from property in junk.Object.GetProperties() select property.Name;
            ROMap mappingTemplate = new ROMap(ManagementPack);
            foreach(ROMapElement e in Questions)
            {
                if ( propertynames.Contains<string>(e.TargetPath, StringComparer.InvariantCulture))
                {
                    mappingTemplate.AddQuestion(e);
                }
                else
                {
                    WriteError(new ErrorRecord(new ArgumentException("Property '" + e.TargetPath + "' does not exist"), "BadQuestionTarget", ErrorCategory.InvalidArgument, e));
                }
            }
 
            string ROName = "Offering." + Guid.NewGuid().ToString("N");
            CreatableEnterpriseManagementObject cemo = new CreatableEnterpriseManagementObject(_mg, _roClass);
            cemo[null, "ID"].Value = ExtensionIdentifier.CreateObjectIdentifier(ManagementPack, ROName, ExtensionIdentifier.CreateTypeIdentifier("RequestOffering")).ToString();
 
            if (Title != null) { cemo[null, "Title"].Value = Title; }
            if (BriefDescription != null) { cemo[null, "BriefDescription"].Value = BriefDescription; }
            if ( Comment != null ) { cemo[null, "Comment"].Value = Comment; }
            if ( DisplayName != null) { cemo[null, "DisplayName"].Value = DisplayName; }
            cemo[null, "Domain"].Value = ManagementPack.Name;
            if ( EstimatedTimeToCompletion != null ) { cemo[null, "EstimatedTimeToCompletion"].Value = EstimatedTimeToCompletion; }
            if ( Notes != null ) { cemo[null, "Notes"].Value = Notes; }
            if ( Overview != null) { cemo[null, "Overview"].Value = Overview; }
            if ( Image != null ) { cemo[null, "Image"].Value = Image; }
            cemo[null, "Path"].Value = ROName;
            cemo[null, "PresentationMappingTemplate"].Value = mappingTemplate.ToString();
            if ( PublishDate != null) { cemo[null, "PublishDate"].Value = PublishDate; }
            if ( Status != null ) { cemo[null, "Status"].Value = SMHelpers.GetEnum(Status, _mg); }
            else { cemo[null, "Status"].Value = SMHelpers.GetEnum("Draft", _mg); }
            // TargetTemplate is an object template, usually a service request, but could be an incident
            cemo[null, "TargetTemplate"].Value = TargetTemplate.Identifier.ToString();
 
            // OK - we've created the bits we needed to create, now hook up the projection
            // and attache the publisher and owner
 
 
 
            EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(cemo);
            if ( RelatedKnowledgeArticle != null )
            {
                ITypeProjectionComponent rel = _roProjection["RelatedKnowledgeArticles"];
                foreach (EnterpriseManagementObject emo in RelatedKnowledgeArticle)
                {
                    emop.Add(emo, rel.TargetEndpoint);
                }
            }
            if (PublishedBy != null)
            {
                ManagementPackRelationship pubRel = _mg.EntityTypes.GetRelationshipClasses(new ManagementPackRelationshipCriteria("Name = 'System.OfferingPublishedBy'")).First();
                emop.Add(PublishedBy, pubRel.Target);
            }
            if (Owner != null)
            {
                ManagementPackRelationship ownRel = _mg.EntityTypes.GetRelationshipClasses(new ManagementPackRelationshipCriteria("Name = 'System.OfferingOwner'")).First();
                emop.Add(Owner, ownRel.Target);
            }
            if ( NoCommit )
            {
                WriteObject(emop);
                return;
            }
            if (ShouldProcess(emop.Object.DisplayName))
            {
                try
                {
                    emop.Commit();
                }
                catch (Exception e)
                {
                    WriteError(new ErrorRecord(e, "CommitFailure", ErrorCategory.NotSpecified, emop));
                }
            }
            if (PassThru) { WriteObject(emop); }
        }
    }
    // This cmdlet can auto generate Service Request data based on a Request Offering
    // or based on a question collection, it can create the Service Request (or anything that the Request Offering
    // Point to
    [Cmdlet(VerbsCommon.New, "SCSMServiceRequest", SupportsShouldProcess = true)]
    public class NewSCSMServiceRequestCommand : PSCmdlet
    {
        #region parameters
        private EnterpriseManagementObjectProjection _requestOffering;
        [Parameter(Position=0,Mandatory=true,ValueFromPipelineByPropertyName=true)]
        public EnterpriseManagementObjectProjection RequestOffering
        {
            get { return _requestOffering; }
            set { _requestOffering = value; }
        }
        private SwitchParameter _auto;
        [Parameter(ParameterSetName="AutoGenerate")]
        public SwitchParameter Auto
        {
            get { return _auto; }
            set { _auto = value; WriteVerbose("This is not activated yet"); }
        }
        private SwitchParameter _noCommit;
        [Parameter]
        public SwitchParameter NoCommit
        {
            get { return _noCommit; }
            set { _noCommit = value; }
        }
        private RequestOfferingQuestion[] _question;
        [Parameter(ParameterSetName = "Question",Position=1,ValueFromPipelineByPropertyName=true)]
        public RequestOfferingQuestion[] Question
        {
            get { return _question; }
            set { _question = value; }
        }
        #endregion
        private Stream fileAttachement = null;
        private ManagementPackRelationship workItemHasFileAttachment;
        private ManagementPackRelationship workItemHasRequestOffering;
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
        }
        private string GetIdPrefix(EnterpriseManagementObjectProjection p)
        {
            string prefix = String.Empty;
            try
            {
                // support two different types ServiceRequest and Incident
                ManagementPackClass c = p.Object.GetLeastDerivedNonAbstractClass();
                Regex r = new Regex("Incident", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
                ManagementPackClass settingsClass;
                string propertyName;
                if (r.Match(c.Name).Success)
                {
                    settingsClass = p.Object.ManagementGroup.EntityTypes.GetClasses(new ManagementPackClassCriteria("Name = 'System.WorkItem.Incident.GeneralSetting'")).First();
                    propertyName = "PrefixForId";
                }
                else
                {
                    settingsClass = p.Object.ManagementGroup.EntityTypes.GetClasses(new ManagementPackClassCriteria("Name = 'System.GlobalSetting.ServiceRequestSettings'")).First();
                    propertyName = "ServiceRequestPrefix";
                }
                EnterpriseManagementObject settingInstance = p.Object.ManagementGroup.EntityObjects.GetObject<EnterpriseManagementObject>(settingsClass.Id, ObjectQueryOptions.Default);
                prefix = settingInstance[null, propertyName].Value as String;
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(e, "RetrievePrefix", ErrorCategory.InvalidOperation, p)) ;
            }
            return prefix;
        }
        protected override void ProcessRecord()
        {
            ManagementPackObjectTemplate t = SMHelpers.GetObjectTemplateFromRequestOffering(RequestOffering);
            EnterpriseManagementGroup EMG = RequestOffering.Object.ManagementGroup;
            EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(RequestOffering.Object.ManagementGroup, t);
            string prefix = GetIdPrefix(emop);
            emop.Object[null, "Id"].Value = String.Format("{0}{{0}}", prefix);
            emop.Object[null, "DisplayName"].Value = String.Format("{0} - {1}", emop.Object[null, "Id"].Value, RequestOffering.Object[null, "Title"].Value);
            workItemHasFileAttachment = RequestOffering.Object.ManagementGroup.EntityTypes.GetRelationshipClasses(new ManagementPackRelationshipCriteria("Name = 'System.WorkItemHasFileAttachment'")).First();
            workItemHasRequestOffering = RequestOffering.Object.ManagementGroup.EntityTypes.GetRelationshipClasses(new ManagementPackRelationshipCriteria("Name = 'System.WorkItemRelatesToRequestOffering'")).First();
            foreach (RequestOfferingQuestion q in Question)
            {
                if (q.SourceControlType != ControlType.FileAttachment)
                {
                    try
                    {
                        if (q.TargetPath != String.Empty)
                        {
                            WriteVerbose("Setting " + q.TargetPath + " to " + q.answer);
                            emop.Object[null, q.TargetPath].Value = q.answer;
                        }
                    }
                    catch (Exception e)
                    {
                        WriteError(new ErrorRecord(e, "ValueAssignment", ErrorCategory.InvalidOperation, q));
                    }
                }
                else
                {
                    // this will be a PATH
                    // in the case where we do not commit, we must add the file stream to the emop so the user can close the
                    // stream
                    // in the case that we do commit, we can close the stream;
                    ProviderInfo pi;
                    string fileName = q.answer.ToString();
                    Collection<string> paths = GetResolvedProviderPathFromPSPath(fileName, out pi);
                    if (paths.Count == 1)
                    {
                        string filePath = paths[0];
                        WriteVerbose("Attaching " + filePath);
                        fileAttachement = File.OpenRead(filePath);
                        ManagementPackClass fileAttachmentClass = EMG.EntityTypes.GetClasses(new ManagementPackClassCriteria("Name = 'System.FileAttachment'")).First();
                        CreatableEnterpriseManagementObject fileAttachmentInstance = new CreatableEnterpriseManagementObject(EMG, fileAttachmentClass);
 
                        fileAttachmentInstance[fileAttachmentClass, "Id"].Value = Guid.NewGuid().ToString();
                        fileAttachmentInstance[fileAttachmentClass, "DisplayName"].Value = fileName;
                        fileAttachmentInstance[fileAttachmentClass, "Description"].Value = fileName;
                        fileAttachmentInstance[fileAttachmentClass, "Extension"].Value = Path.GetExtension(filePath);
                        fileAttachmentInstance[fileAttachmentClass, "Size"].Value = (int)fileAttachement.Length;
                        fileAttachmentInstance[fileAttachmentClass, "AddedDate"].Value = DateTime.Now.ToUniversalTime();
                        fileAttachmentInstance[fileAttachmentClass, "Content"].Value = fileAttachement;
 
                        emop.Add(fileAttachmentInstance, workItemHasFileAttachment.Target);
                    }
                    else
                    {
                        WriteWarning(q.answer.ToString() + "does not resolve to a single path, not attaching file");
                    }
                }
            }
            try
            {
                string userInputString = GetUserInputString();
                WriteVerbose("Setting UserInput to " + userInputString);
 
                emop.Object[null, "UserInput"].Value = userInputString;
            }
            catch ( Exception e)
            {
                WriteError(new ErrorRecord(e, "UserInputAssigmentFailure", ErrorCategory.InvalidOperation, emop));
            }
            try
            {
                emop.Add(RequestOffering, workItemHasRequestOffering.Target);
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(e, "RelationshipToRequestOffering", ErrorCategory.InvalidOperation, emop));
            }
            if (NoCommit)
            {
                WriteObject(emop);
                return;
            }
            else
            {
                try
                {
                    if (ShouldProcess(emop.Object.DisplayName))
                    {
                        WriteVerbose("Committing " + emop.Object.DisplayName);
                        emop.Commit();
                    }
                }
                catch (Exception e)
                {
                    WriteError(new ErrorRecord(e, "Commit Failure", ErrorCategory.InvalidOperation, emop));
                }
                finally
                {
                    if ( fileAttachement != null ) { fileAttachement.Close(); fileAttachement.Dispose(); }
                }
            }
 
        }
        private string GetUserInputString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<UserInputs>");
            foreach (RequestOfferingQuestion q in Question)
            {
                sb.AppendFormat(@" <UserInput Question=""{0}"" Answer=""{1}"" Type=""{2}"" />", q.Prompt, q.answer, q.stringMapper[q.SourceControlType].OutputType);
            }
            sb.Append("</UserInputs>");
            return sb.ToString();
        }
    }
 
    [Cmdlet(VerbsCommon.Get, "SCSMRequestOfferingQuestion")]
    public class GetSCSMRequestOfferingQuestionCommand : PSCmdlet
    {
        #region parameters
        private EnterpriseManagementObjectProjection[] _requestOffering;
        [Parameter(Position=0,Mandatory=true,ValueFromPipeline=true)]
        public EnterpriseManagementObjectProjection[] RequestOffering
        {
            get { return _requestOffering; }
            set { _requestOffering = value; }
        }
        #endregion
        protected override void BeginProcessing()
        {
            base.BeginProcessing();
        }
        protected override void ProcessRecord()
        {
            foreach (EnterpriseManagementObjectProjection p in RequestOffering)
            {
                string PMT;
                try
                {
                    PMT = p.Object[null, "PresentationMappingTemplate"].Value.ToString();
                }
                catch ( Exception e )
                {
                    WriteError(new ErrorRecord(e, "NoPresentationMappingTemplate", ErrorCategory.ObjectNotFound, p));
                    break;
                }
                XmlDocument xdoc = new XmlDocument();
                xdoc.LoadXml(PMT);
                foreach (RequestOfferingQuestion e in GetROQuestions(xdoc))
                {
                    e.RequestOffering = p;
                    e.RequestOfferingName = p.Object[null, "Title"].Value.ToString();
                    // Last chance to find our listID
                    if (e.SourceControlType == ControlType.List && e.ListId == Guid.Empty)
                    {
                        try
                        {
                            e.ListId = GetListIdFromRO(p, e.TargetPath);
                        }
                        catch ( Exception ex )
                        {
                            WriteError(new ErrorRecord(ex, "badListId", ErrorCategory.InvalidOperation, xdoc));
                        }
                    }
                    WriteObject(e);
                }
            }
        }
        private Guid GetListIdFromRO(EnterpriseManagementObjectProjection p, string propertyName)
        {
            ManagementPackObjectTemplate t = SMHelpers.GetObjectTemplateFromRequestOffering(p); // p.Object.ManagementGroup.Templates.GetObjectTemplates(new ManagementPackObjectTemplateCriteria("Name = '" + p.Object[null, "TargetTemplate"].Value.ToString().Split('|')[3] + "'")).First();
            EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(p.Object.ManagementGroup, t);
            return emop.Object[null, propertyName].Type.EnumType.Id;
        }
        private List<RequestOfferingQuestion> GetROQuestions(XmlDocument doc)
        {
            List<RequestOfferingQuestion> myQuestions = new List<RequestOfferingQuestion>();
            XPathNavigator nav = doc.CreateNavigator();
            XPathExpression exp = nav.Compile("/Object/Data/PresentationMappingTemplate/Sources/Source");
            exp.AddSort("@Ordinal", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Number);
            // XmlNodeList questions = pmtXML.SelectNodes("/Object/Data/PresentationMappingTemplate/Sources/Source") ;
            XPathNodeIterator questions = nav.Select(exp);
            string prompt = "";
            string target = "";
            string type = "";
            int ordinal = 0;
            bool optional = true;
            foreach (XPathNavigator q in questions)
            {
                XmlNode question = ((IHasXmlNode)q).GetNode();
                if (question.Attributes.GetNamedItem("Id").Value != Guid.Empty.ToString())
                {
 
                    try { prompt = question.Attributes.GetNamedItem("Prompt").Value.ToString(); }
                    catch { prompt = String.Empty; }
                    try { target = question.SelectSingleNode("Targets/Target").Attributes.GetNamedItem("Path").Value; }
                    catch { target = String.Empty; }
                    string controlType = question.Attributes.GetNamedItem("ControlType").Value;
                    try { type = question.SelectSingleNode("ControlConfiguration/AddressableOutputs/AddressableOutput").Attributes.GetNamedItem("OutputType").Value; }
                    catch { type = string.Empty; }
                    try { ordinal = int.Parse(question.Attributes.GetNamedItem("Ordinal").Value); }
                    catch { ordinal = 0; }
                    try { optional = bool.Parse(question.Attributes.GetNamedItem("Optional").Value); }
                    catch { optional = true; }
                    RequestOfferingQuestion roq = new RequestOfferingQuestion();
                    roq.Prompt = prompt;
                    roq.TargetPath = target;
                    roq.Optional = optional;
                    roq.Ordinal = ordinal;
                    // roq.SourceControlType
                    foreach (var k in roq.stringMapper.Keys)
                    {
                        if (roq.stringMapper[k].ControlTypeString == controlType) { roq.SourceControlType = k; }
                    }
                    if (roq.SourceControlType == ControlType.List)
                    {
                        // Try this first, not all lists provide an id for the enum
                        try
                        {
                            roq.ListId = new Guid(question.SelectSingleNode("ControlConfiguration/AddressableOutputs/AddressableOutput").Attributes.GetNamedItem("OutputTypeMetadata").Value);
                        }
                        catch
                        {
                            ;
                        }
                    }
                    if (roq.SourceControlType == ControlType.InlineList)
                    {
                        int count = question.SelectNodes("ControlConfiguration/Configuration/Details/ListValue").Count;
                        List<string> listElements = new List<string>();
                        foreach(XmlNode n in question.SelectNodes("ControlConfiguration/Configuration/Details/ListValue"))
                        {
                            listElements.Add(n.Attributes.GetNamedItem("DisplayName").Value);
                        }
                        roq.InlineListElements = listElements.ToArray();
                    }
                    myQuestions.Add(roq);
 
                }
            }
            return myQuestions;
        }
 
    }
    public class RequestOfferingQuestion : ROMapElement
    {
        public object answer;
        public EnterpriseManagementObjectProjection RequestOffering;
        public string RequestOfferingName;
        public RequestOfferingQuestion() { ; }
    }
    [Cmdlet(VerbsCommon.New, "SCSMRequestOfferingQuestion")]
    public class NewSCSMRequestOfferingQuestionCommand : ObjectCmdletHelper, IDynamicParameters
    {
        #region parameters
        private string _prompt;
        [Parameter(Position = 0, Mandatory = true, ValueFromPipelineByPropertyName = true)]
        public string Prompt
        {
            get { return _prompt; }
            set { _prompt = value; }
        }
        private string _targetPath;
        [Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true)]
        public string TargetPath
        {
            get { return _targetPath; }
            set { _targetPath = value; }
        }
        private ControlType _type;
        [Parameter(Position = 2, Mandatory = true, ValueFromPipelineByPropertyName = true)]
        public ControlType Type
        {
            get { return _type; }
            set { _type = value; }
        }
        private SwitchParameter _mandatory;
        [Parameter]
        public SwitchParameter Mandatory
        {
            get { return _mandatory; }
            set { _mandatory = value; }
        }
        private SendInlineListParameter inlineList;
        private SendEnumerationListParameter enumerationList;
 
        public object GetDynamicParameters()
        {
            if ( Type == ControlType.InlineList )
            {
                inlineList = new SendInlineListParameter();
                return inlineList;
            }
            if (Type == ControlType.List)
            {
                enumerationList = new SendEnumerationListParameter();
                return enumerationList;
            }
            return null;
        }
        #endregion
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            ROMapElement question = new ROMapElement();
            question.Prompt = Prompt;
            question.TargetPath = TargetPath;
            question.SourceControlType = Type;
            if ( Mandatory )
            {
                question.Optional = false;
            }
            switch (Type)
            {
                case ControlType.List:
                {
                    question.ListId = enumerationList.EnumerationList.Id;
                    break;
                }
                case ControlType.InlineList:
                {
                    question.InlineListElements = inlineList.ListElements;
                    break;
                }
                default: { break; }
            }
            WriteObject(question);
        }
    }
    public class SendInlineListParameter
    {
        private string[] _listElements;
        [Parameter(Mandatory = true, Position = 3, ValueFromPipelineByPropertyName = true)]
        public string[] ListElements
        {
            get { return _listElements; }
            set { _listElements = value; }
        }
    }
    public class SendEnumerationListParameter
    {
        private ManagementPackEnumeration _enumerationList;
        [Parameter(Mandatory = true, Position = 3, ValueFromPipelineByPropertyName = true)]
        public ManagementPackEnumeration EnumerationList
        {
            get { return _enumerationList; }
            set { _enumerationList = value; }
        }
    }
    // TODO: There may be something wrong with this, it shows up appropriately in the tool, but not in
    // in the website
    [Cmdlet(VerbsCommon.New, "SCSMServiceOffering", SupportsShouldProcess = true)]
    public class NewSCSMServiceOfferingCommand : ObjectCmdletHelper
    {
        #region parameters
        private String _briefDescription;
        [Parameter]
        public String BriefDescription
        {
            get { return _briefDescription; }
            set { _briefDescription = value; }
        }
        private String _category;
        [Parameter]
        public String Category
        {
            get { return _category; }
            set { _category = value; }
        }
        private String _comment;
        [Parameter]
        public String Comment
        {
            get { return _comment; }
            set { _comment = value; }
        }
        private String _costInformation;
        [Parameter]
        public String CostInformation
        {
            get { return _costInformation; }
            set { _costInformation = value; }
        }
        private Uri _costInformationLink;
        [Parameter]
        public Uri CostInformationLink
        {
            get { return _costInformationLink; }
            set { _costInformationLink = value; }
        }
        private String _displayName;
        [Parameter]
        public String DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }
        private Stream _image;
        [Parameter]
        public Stream Image
        {
            get { return _image; }
            set { _image = value; }
        }
        private String _notes;
        [Parameter]
        public String Notes
        {
            get { return _notes; }
            set { _notes = value; }
        }
        private String _overview;
        [Parameter]
        public String Overview
        {
            get { return _overview; }
            set { _overview = value; }
        }
        private DateTime ? _publishDate;
        [Parameter]
        public DateTime ? PublishDate
        {
            get { return _publishDate; }
            set { _publishDate = value; }
        }
        private String _sLAInformation;
        [Parameter]
        public String SLAInformation
        {
            get { return _sLAInformation; }
            set { _sLAInformation = value; }
        }
        private Uri _sLAInformationLink;
        [Parameter]
        public Uri SLAInformationLink
        {
            get { return _sLAInformationLink; }
            set { _sLAInformationLink = value; }
        }
        private string _status;
        [Parameter]
        public string Status
        {
            get { return _status; }
            set { _status = value; }
        }
        private String _title;
        [Parameter(Mandatory = true)]
        public String Title
        {
            get { return _title; }
            set { _title = value; }
        }
        private EnterpriseManagementObject _owner;
        [Parameter]
        public EnterpriseManagementObject Owner
        {
            get { return _owner; }
            set { _owner = value; }
        }
        private EnterpriseManagementObject _publishedBy;
        [Parameter]
        public EnterpriseManagementObject PublishedBy
        {
            get { return _publishedBy; }
            set { _publishedBy = value; }
        }
 
        private EnterpriseManagementObject[] _requestOffering;
        [Parameter]
        public EnterpriseManagementObject[] RequestOffering
        {
            get { return _requestOffering; }
            set { _requestOffering = value; }
        }
        private EnterpriseManagementObject[] _relatedKnowledgeArticle;
        [Parameter]
        public EnterpriseManagementObject[] RelatedKnowledgeArticle
        {
            get { return _relatedKnowledgeArticle; }
            set { _relatedKnowledgeArticle = value; }
        }
        private EnterpriseManagementObject[] _relatedService;
        [Parameter]
        public EnterpriseManagementObject[] RelatedService
        {
            get { return _relatedService; }
            set { _relatedService = value; }
        }
        private ManagementPack _managementPack;
        [Parameter(Mandatory = true, Position = 0)]
        public ManagementPack ManagementPack
        {
            get { return _managementPack; }
            set { _managementPack = value; }
        }
        private SwitchParameter _passThru;
        [Parameter]
        public SwitchParameter PassThru
        {
            get { return _passThru; }
            set { _passThru = value; }
        }
        #endregion
 
        private string[] classMembers = { "BriefDescription", "Category", "Comment", "CostInformation", "CostInformationLink",
                                            "DisplayName", "Image", "Notes", "Overview", "PublishDate", "SLAInformation",
                                            "SLAInformationLink", "Status", "Title" };
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            ManagementPack catalogMP = SMHelpers.GetManagementPack("System.ServiceCatalog.Library", _mg);
            ManagementPackClass SOClass = SMHelpers.GetManagementPackClass("System.ServiceOffering", catalogMP);
            ManagementPack projectionMP = SMHelpers.GetManagementPack("ServiceManager.ServiceCatalog.Library", _mg);
            ManagementPackTypeProjection SOProjectionType = SMHelpers.GetManagementPackTypeProjection("System.ServiceOffering.ProjectionType",projectionMP);
            ManagementPackTypeProjection projectionType = SMHelpers.GetManagementPackTypeProjection("System.Extensibility.ManagementPackServiceOffering.Projection", SMHelpers.GetManagementPack("System.ServiceCatalog.Library", _mg));
            EnterpriseManagementObjectProjection projection = new EnterpriseManagementObjectProjection(_mg, SOClass);
            CreatableEnterpriseManagementObject cemo = new CreatableEnterpriseManagementObject(_mg, SOClass);
            ExtensionIdentifier ServiceOfferingTypeId = ExtensionIdentifier.CreateTypeIdentifier("ServiceOffering");
            string ServiceOfferingName = String.Format("Offering.{0}", Guid.NewGuid().ToString("N"));
            string ServiceOfferingID = ExtensionIdentifier.CreateObjectIdentifier(ManagementPack, ServiceOfferingName, ServiceOfferingTypeId).ToString();
            projection.Object[SOClass, "ID"].Value = ServiceOfferingID;
            projection.Object[SOClass, "Domain"].Value = ManagementPack.Name;
            projection.Object[null, "CultureName"].Value = String.Empty;
            #region SetSeedProperties
            Hashtable ht = new Hashtable(StringComparer.OrdinalIgnoreCase);
            foreach (ManagementPackProperty prop in cemo.GetProperties())
            {
                ht.Add(prop.Name, prop);
            }
            Type t = this.GetType();
            foreach(string s in classMembers)
            {
                PropertyInfo mi = t.GetMember(s).GetValue(0) as PropertyInfo;
                object o = mi.GetValue(this, null);
                if (o == null)
                {
                    WriteVerbose(s + " is not set");
                }
                else
                {
                    WriteVerbose(s + " is set to " + o.ToString());
                    ManagementPackProperty p = ht[s] as ManagementPackProperty;
                    AssignNewValue(p, projection.Object[p], o);
                }
            }
            #endregion
            #region SetRelationships
            if (RelatedKnowledgeArticle != null)
            {
                ITypeProjectionComponent rel = SOProjectionType["RelatedKnowledgeArticles"];
                foreach (EnterpriseManagementObject emo in RelatedKnowledgeArticle)
                {
                    projection.Add(emo, rel.TargetEndpoint);
                }
            }
            if (RelatedService != null)
            {
                ITypeProjectionComponent rel = SOProjectionType["RelatedServices"];
                foreach (EnterpriseManagementObject emo in RelatedKnowledgeArticle)
                {
                    projection.Add(emo, rel.TargetEndpoint);
                }
            }
            if (RequestOffering != null)
            {
                ITypeProjectionComponent rel = SOProjectionType["RequestOfferings"];
                foreach (EnterpriseManagementObject emo in RequestOffering)
                {
                    projection.Add(emo, rel.TargetEndpoint);
                }
            }
            if (Owner != null)
            {
                ITypeProjectionComponent rel = SOProjectionType["Owner"];
                projection.Add(Owner, rel.TargetEndpoint);
            }
            if (PublishedBy != null)
            {
                ITypeProjectionComponent rel = SOProjectionType["PublishedBy"];
                projection.Add(PublishedBy, rel.TargetEndpoint);
            }
            #endregion
            if (ShouldProcess(projection.Object.DisplayName))
            {
                projection.Commit();
                if (PassThru)
                {
                    WriteObject(ServiceManagerObjectHelper.AdaptProjection(this, projection, SOProjectionType.Name));
                }
            }
        }
    }
      
    // [Cmdlet(VerbsCommon.Set, "SCSMServiceOffering", SupportsShouldProcess = true)]
    // [Cmdlet(VerbsCommon.Set, "SCSMRequestOffering", SupportsShouldProcess = true)]
     
    public enum ControlType
    {
        String,
        DateTime,
        Double,
        FileAttachment,
        Integer,
        List,
        InlineList,
        Boolean
    };
 
    public class stringMap
    {
        public string OutputType;
        public string OutputName;
        public string ControlTypeString;
        public stringMap(string t, string n, string c)
        {
            OutputType = t;
            OutputName = n;
            ControlTypeString = c;
        }
    }
 
    public class ROMap
    {
        public List<ROMapElement> Elements;
        public ManagementPack myMP;
        public int currentQuestion = 1;
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"<Object ID=""1|{0}|1.0.0.0|Offering{1}/GeneratedId_PresentationMappingTemplate0|4|RequestOffering/PresentationMappingTemplate"">", myMP.Name, Guid.NewGuid().ToString("N"));
            sb.Append("<References>");
            sb.AppendFormat(@"<Reference Alias=""EnterpriseManagement"" Name=""Microsoft.EnterpriseManagement.ServiceManager.UI.Console"" KeyToken=""31bf3856ad364e35"" Version=""7.5.1088.205"" />");
            sb.AppendFormat(@"<Reference Alias=""Alias_1"" Name=""ServiceManager.ServiceRequest.Library"" KeyToken=""31bf3856ad364e35"" Version=""7.5.1088.205"" />");
            sb.Append("</References>");
            sb.Append("<Data>");
            sb.Append("<PresentationMappingTemplate>");
            sb.Append("<Sources>");
            sb.Append(@"<Source Id=""00000000-0000-0000-0000-000000000000"" Ordinal=""0"" ReadOnly=""false"" Optional=""false"" ControlType=""System.SupportingItem.PortalControl"" >");
            sb.Append(@"<ControlConfiguration>");
            sb.Append(@"<Dependencies />");
            sb.Append(@"<AddressableOutputs>");
            sb.Append(@"<AddressableOutput OutputName=""Token: Portal User Name"" OutputType=""string"" />");
            sb.Append(@"</AddressableOutputs>");
            sb.Append(@"</ControlConfiguration>");
            sb.Append(@"<Targets />");
            sb.Append(@"</Source>");
            foreach (ROMapElement e in Elements)
            {
                sb.Append(e.ToString());
            }
            sb.Append("</Sources>");
            sb.Append("</PresentationMappingTemplate>");
            sb.Append("</Data>");
            sb.Append("</Object>");
            return sb.ToString();
        }
        public string ToIndentedString()
        {
            StringBuilder sb = new StringBuilder();
            StringWriter stream = new StringWriter(sb);
            XmlTextWriter xmlWriter = new XmlTextWriter(stream);
            xmlWriter.Formatting = Formatting.Indented;
            XmlDocument xmlblob = new XmlDocument();
            string s = this.ToString();
            xmlblob.LoadXml(s);
            xmlblob.WriteTo(xmlWriter);
            return sb.ToString();
        }
        private ROMap()
        {
            Elements = new List<ROMapElement>();
        }
        public ROMap(ManagementPack m)
        {
            Elements = new List<ROMapElement>();
            myMP = m;
        }
 
        public void AddQuestion(string prompt, string targetPath, ControlType pathType)
        {
            // handle ControlTypes which we do in other places
            if (pathType == ControlType.List) { throw new ArgumentException("Use AddListQuestion for adding an enum list"); }
            if (pathType == ControlType.InlineList) { throw new ArgumentException("Use AddInlineListQuestion for adding a simple list"); }
            ROMapElement element = new ROMapElement();
            element.Ordinal = currentQuestion++;
            element.Prompt = prompt;
            element.TargetPath = targetPath;
            element.SourceControlType = pathType;
            // TODO: VALIDATION
            this.Elements.Add(element);
        }
        // this is for a simple list
        public void AddInlineListQuestion(string prompt, string targetPath, string[] listElements)
        {
            ROMapElement element = new ROMapElement();
            element.Ordinal = currentQuestion++;
            element.Prompt = prompt;
            element.TargetPath = targetPath;
            element.SourceControlType = ControlType.InlineList;
            element.InlineListElements = listElements;
            this.Elements.Add(element);
        }
        // add an enum type
        public void AddListQuestion(string prompt, string targetPath, ManagementPackEnumeration enumList)
        {
            ROMapElement element = new ROMapElement();
            element.Ordinal = currentQuestion++;
            element.Prompt = prompt;
            element.TargetPath = targetPath;
            element.SourceControlType = ControlType.List;
            element.ListId = enumList.Id;
            this.Elements.Add(element);
        }
        // This will overwrite the ordinal if it's passed
        public void AddQuestion(ROMapElement e)
        {
            e.Ordinal = currentQuestion++;
            this.Elements.Add(e);
        }
        public List<ValidationResult> Validate(EnterpriseManagementObjectProjection p)
        {
            List<ValidationResult> myResults = new List<ValidationResult>();
            foreach (ROMapElement element in this.Elements)
            {
                ValidationResult mystatus = new ValidationResult();
                mystatus.PropertyName = element.TargetPath;
                mystatus.PropertyType = element.GetControlTypeString(element.SourceControlType);
                mystatus.Status = MappingValidationStatus.ERROR;
                foreach (ManagementPackProperty prop in p.Object.GetProperties())
                {
                    if (string.Compare(element.TargetPath, prop.Name) == 0)
                    {
                        mystatus.Status = MappingValidationStatus.OK;
                        mystatus.Message = "Map ok: " + prop.Name;
                        break;
                    }
                }
                if (mystatus.Status != MappingValidationStatus.OK)
                {
                    mystatus.Message = String.Format("Map fail: no property '{0}' in {1}", element.TargetPath, p.Object.Name);
                }
                myResults.Add(mystatus);
            }
            return myResults;
        }
    }
 
    public class ROMapElement
    {
        public Guid Id;
        public int Ordinal;
        public string Prompt;
        public bool ReadOnly; // default is false
        public bool Optional = true;
        public ControlType SourceControlType = ControlType.String;
        public Guid ListId; // note that this will only be available when the ControlType is List this is the id of the parent enum
        public string[] InlineListElements;
        public int DefaultListElement;
        public string TargetPath;
        public Dictionary<ControlType, stringMap> stringMapper;
        public ROMapElement()
        {
            Id = Guid.NewGuid();
            stringMapper = new Dictionary<ControlType, stringMap>();
            stringMapper.Add(ControlType.Boolean, new stringMap("bool", "True/False", "System.SupportingItem.PortalControl.Boolean"));
            stringMapper.Add(ControlType.DateTime, new stringMap("datetime", "Date", "System.SupportingItem.PortalControl.DateTime"));
            stringMapper.Add(ControlType.Double, new stringMap("double", "Decimal", "System.SupportingItem.PortalControl.Double"));
            stringMapper.Add(ControlType.FileAttachment, new stringMap(String.Empty, String.Empty, "System.SupportingItem.PortalControl.FileAttachment"));
            stringMapper.Add(ControlType.InlineList, new stringMap("string", "ListValue", "System.SupportingItem.PortalControl.InlineList"));
            stringMapper.Add(ControlType.Integer, new stringMap("int", "Integer", "System.SupportingItem.PortalControl.Integer"));
            stringMapper.Add(ControlType.List, new stringMap("list", "List Item", "System.SupportingItem.PortalControl.List"));
            stringMapper.Add(ControlType.String, new stringMap("string", "String", "System.SupportingItem.PortalControl.String"));
        }
        public string GetControlTypeString(ControlType t)
        {
            return stringMapper[t].ControlTypeString;
        }
        public override string ToString()
        {
            if (SourceControlType == ControlType.InlineList && InlineListElements == null) { throw new InvalidOperationException("List types must be populated"); }
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"<Source Id=""{0}"" Ordinal=""{1}"" Prompt=""{2}"" ReadOnly=""{3}"" Optional=""{4}"" ControlType=""{5}"">",
                Id, Ordinal, Prompt, ReadOnly.ToString().ToLower(), Optional.ToString().ToLower(), GetControlTypeString(SourceControlType));
            sb.Append("<ControlConfiguration>");
            sb.Append("<Dependencies />");
 
 
            if (SourceControlType == ControlType.InlineList)
            {
                sb.Append("<AddressableOutputs>");
                sb.Append(@"<AddressableOutput OutputName=""ListValue"" OutputType=""string"" />");
                sb.Append("</AddressableOutputs>");
                sb.Append("<Configuration>");
                sb.Append("<Details>");
                int i = 0;
                foreach (string s in InlineListElements)
                {
                    bool isDefault;
                    if (i == DefaultListElement) { isDefault = true; } else { isDefault = false; }
                    sb.AppendFormat(@"<ListValue DisplayName=""{0}"" IsDefault=""{1}"" />", s, isDefault.ToString().ToLower());
                    i++;
                }
                sb.Append("</Details>");
                sb.Append("</Configuration>");
            }
            else if (SourceControlType == ControlType.FileAttachment)
            {
                sb.Append("<AddressableOutputs />");
            }
            else if (SourceControlType == ControlType.List)
            {
                sb.Append("<AddressableOutputs>");
                sb.AppendFormat(@"<AddressableOutput OutputName=""{0}"" OutputType=""enum"" OutputTypeMetadata=""{1}"" />", stringMapper[SourceControlType].OutputName, ListId);
                sb.Append("</AddressableOutputs>");
            }
            else
            {
                sb.Append("<AddressableOutputs>");
                sb.AppendFormat(@"<AddressableOutput OutputName=""{0}"" OutputType=""{1}"" />", stringMapper[SourceControlType].OutputName, stringMapper[SourceControlType].OutputType);
                sb.Append("</AddressableOutputs>");
            }
            sb.Append("</ControlConfiguration>");
            if (TargetPath == null || SourceControlType == ControlType.FileAttachment)
            {
                sb.Append("<Targets />");
            }
            else
            {
                sb.Append("<Targets>");
                sb.AppendFormat(@"<Target Path=""{0}"" OutputName=""{1}"" />", TargetPath, stringMapper[SourceControlType].OutputName);
                sb.Append("</Targets>");
            }
            sb.Append("</Source>");
 
            return sb.ToString();
        }
    }
    public enum MappingValidationStatus { OK, ERROR };
    public class ValidationResult
    {
        public string PropertyName;
        public string PropertyType;
        public MappingValidationStatus Status;
        public string Message;
    }
 
}
#endif