Inheritance: SoapTypeElement
        public static ISoapTypeElement GetSoapType <SoapType>(Guid typeUid) where SoapType : ISoapTypeElement
        {
            lock (_lock)
            {
                if (_soapTypes.ContainsKey(typeUid))
                {
                    return(_soapTypes[typeUid]);
                }

                using (MappingToolDatabaseDataContext mappingDb = new MappingToolDatabaseDataContext())
                {
                    if (typeof(SoapType).IsAssignableFrom(typeof(SoapNodeType)))
                    {
                        var nodeType = (from dbNodeType in mappingDb.NodeTypes where dbNodeType.NodeTypeUid == typeUid select dbNodeType).First();

                        SoapNodeType soapNodeType = new SoapNodeType();
                        soapNodeType.Id   = nodeType.NodeTypeUid;
                        soapNodeType.Name = nodeType.NodeTypeName;

                        return((ISoapTypeElement)soapNodeType);
                    }
                    else if (typeof(SoapType).IsAssignableFrom(typeof(SoapDescriptorType)))
                    {
                        var nodeType = (from dbNodeType in mappingDb.DescriptorTypes where dbNodeType.DescriptorTypeUid == typeUid select dbNodeType).First();

                        SoapDescriptorType soapDescriptorType = new SoapDescriptorType();
                        soapDescriptorType.Id   = nodeType.DescriptorTypeUid;
                        soapDescriptorType.Name = nodeType.DescriptorTypeName;

                        return((ISoapTypeElement)soapDescriptorType);
                    }
                    else if (typeof(SoapType).IsAssignableFrom(typeof(SoapRelationshipType)))
                    {
                        var nodeType = (from dbNodeType in mappingDb.RelationshipTypes where dbNodeType.RelationshipTypeUid == typeUid select dbNodeType).First();

                        SoapRelationshipType soapRelationshipType = new SoapRelationshipType();
                        soapRelationshipType.Id   = nodeType.RelationshipTypeUid;
                        soapRelationshipType.Name = nodeType.RelationshipTypeName;

                        return((ISoapTypeElement)soapRelationshipType);
                    }
                    else if (typeof(SoapType).IsAssignableFrom(typeof(SoapMetadataType)))
                    {
                        var nodeType = (from dbNodeType in mappingDb.MetadataTypes where dbNodeType.MetadataTypeUid == typeUid select dbNodeType).First();

                        SoapMetadataType soapMetadataType = new SoapMetadataType();
                        soapMetadataType.Id   = nodeType.MetadataTypeUid;
                        soapMetadataType.Name = nodeType.MetadataTypeName;

                        return((ISoapTypeElement)soapMetadataType);
                    }
                    else
                    {
                        throw new NotSupportedException("The requested type is not supported");
                    }
                }
            }
        }
        public SoapNode CreateNewDomain(string domainName)
        {
            SoapNode soapDomainNode = null;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (MappingToolDatabaseDataContext mappingDb = new MappingToolDatabaseDataContext())
                {
                    var nodeTypes = from dbNodeTypes in mappingDb.NodeTypes where dbNodeTypes.NodeTypeName == "DomainNode" select dbNodeTypes;
                    var metadataTypes = from dbMetadataTypes in mappingDb.MetadataTypes where dbMetadataTypes.MetadataTypeName == "string" select dbMetadataTypes;

                    NodeType nodeType = nodeTypes.First();
                    MetadataType metadataType = metadataTypes.First();

                    Domain domain = new Domain();
                    domain.DomainUid = Guid.NewGuid();

                    mappingDb.Domains.InsertOnSubmit(domain);
                    mappingDb.SubmitChanges();

                    Node domainNode = new Node();
                    domainNode.DomainUid = domain.DomainUid;
                    domainNode.NodeUid = Guid.NewGuid();
                    domainNode.NodeType = nodeType;
                    domainNode.NodeTypeUid = nodeType.NodeTypeUid;

                    mappingDb.Nodes.InsertOnSubmit(domainNode);
                    mappingDb.SubmitChanges();

                    SoapMetadataType soapMetadataType = new SoapMetadataType();
                    soapMetadataType.Id = metadataType.MetadataTypeUid;
                    soapMetadataType.Name = metadataType.MetadataTypeName;

                    soapDomainNode = UpdateNodeMetadata(domain.DomainUid, domainNode.NodeUid, Guid.Empty, null, "Name", domainName, soapMetadataType);
                }
            });
            return soapDomainNode;
        }
        public List<SoapTypeElement> GetAllSoapTypes()
        {
            List<SoapTypeElement> soapTypes = new List<SoapTypeElement>();
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (MappingToolDatabaseDataContext mappingDb = new MappingToolDatabaseDataContext())
                {
                    var metadataTypes = from dbMetadataTypes in mappingDb.MetadataTypes select dbMetadataTypes;
                    var nodeTypes = from dbNodeTypes in mappingDb.NodeTypes select dbNodeTypes;
                    var descriptorTypes = from dbDescriptorTypes in mappingDb.DescriptorTypes select dbDescriptorTypes;
                    var relationshipTypes = from dbRelationshipTypes in mappingDb.RelationshipTypes select dbRelationshipTypes;

                    foreach (var metadataType in metadataTypes)
                    {
                        SoapMetadataType soapMetadataType = new SoapMetadataType();
                        soapMetadataType.Id = metadataType.MetadataTypeUid;
                        soapMetadataType.Name = metadataType.MetadataTypeName;

                        soapTypes.Add(soapMetadataType);
                    }

                    foreach (var nodeType in nodeTypes)
                    {
                        SoapNodeType soapNodeType = new SoapNodeType();
                        soapNodeType.Id = nodeType.NodeTypeUid;
                        soapNodeType.Name = nodeType.NodeTypeName;

                        soapTypes.Add(soapNodeType);
                    }

                    foreach (var descriptorType in descriptorTypes)
                    {
                        SoapDescriptorType soapDescriptorType = new SoapDescriptorType();
                        soapDescriptorType.Id = descriptorType.DescriptorTypeUid;
                        soapDescriptorType.Name = descriptorType.DescriptorTypeName;

                        soapTypes.Add(soapDescriptorType);
                    }

                    foreach (var relationshipType in relationshipTypes)
                    {
                        SoapRelationshipType soapRelationshipType = new SoapRelationshipType();
                        soapRelationshipType.Id = relationshipType.RelationshipTypeUid;
                        soapRelationshipType.Name = relationshipType.RelationshipTypeName;

                        soapTypes.Add(soapRelationshipType);
                    }
                }
            });
            return soapTypes;
        }
        private static SoapMetadata UpdateMetadata(MappingToolDatabaseDataContext mappingDb, Guid soapNodeId, Guid soapRelationshipId, SoapDescriptorType soapDescriptorType, string metadataName, string metadataValue, SoapMetadataType soapMetadataType, Node node)
        {
            SoapMetadata soapMetadata = new SoapMetadata();
            soapMetadata.MetadataName = metadataName;
            soapMetadata.MetadataValue = metadataValue;
            soapMetadata.MetadataType = soapMetadataType;

            bool existingMetaData = false;
            foreach (Metadata metadatum in node.Metadatas.Where(x => x.MetadataName == metadataName))
            {
                if (soapNodeId != Guid.Empty)
                {
                    if (metadatum.NodeUid != soapNodeId)
                    {
                        continue;
                    }
                }
                if (soapRelationshipId != Guid.Empty)
                {
                    if (metadatum.RelationshipUid != soapRelationshipId)
                    {
                        continue;
                    }
                }
                if (soapDescriptorType != null)
                {
                    if (metadatum.DescriptorTypeUid != soapDescriptorType.Id)
                    {
                        continue;
                    }
                }
                existingMetaData = true;
                if (metadatum.MetadataTypeUid != soapMetadataType.Id)
                {
                    //change in MetadataType
                     metadatum.MetadataType = mappingDb.MetadataTypes.Single(mdt => mdt.MetadataTypeUid == soapMetadataType.Id);
                }
                metadatum.MetadataValue = metadataValue;
                break;
            }
            if (!existingMetaData)
            {
                Metadata metadata = new Metadata();
                metadata.MetadataId = Guid.NewGuid();
                metadata.MetadataTypeUid = soapMetadataType.Id;

                if (soapNodeId != Guid.Empty)
                {
                    metadata.NodeUid = soapNodeId;
                }

                if (soapRelationshipId != Guid.Empty)
                {
                    metadata.RelationshipUid = soapRelationshipId;
                }

                if (soapDescriptorType != null)
                {
                    metadata.DescriptorTypeUid = soapDescriptorType.Id;
                }

                metadata.MetadataName = metadataName;
                metadata.MetadataValue = metadataValue;

                node.Metadatas.Add(metadata);
            }

            return soapMetadata;
        }
        public SoapNode UpdateNodeMetadata(Guid domainId, Guid soapNodeId, Guid soapRelationshipId, SoapDescriptorType soapDescriptorType, string metadataName, string metadataValue, SoapMetadataType soapMetadataType)
        {
            SoapNode soapNode = null;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (MappingToolDatabaseDataContext mappingDb = new MappingToolDatabaseDataContext())
                {
                    var nodes = from dbNode in mappingDb.Nodes where dbNode.DomainUid == domainId && dbNode.NodeUid == soapNodeId select dbNode;

                    var node = nodes.First();

                    SoapMetadata soapMetadata = UpdateMetadata(mappingDb, soapNodeId, soapRelationshipId, soapDescriptorType, metadataName, metadataValue, soapMetadataType, node);
                    soapNode = node.ToSoapObject();
                    mappingDb.SubmitChanges();
                }
            });
            return soapNode;
        }
        public Guid CreateNewMap(Guid domainId, string mapName)
        {
            Guid newMapUid = Guid.Empty;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                Node mapNode = null;
                using (MappingToolDatabaseDataContext mappingDb = new MappingToolDatabaseDataContext())
                {
                    var mapNodeTypes = from dbNodeTypes in mappingDb.NodeTypes where dbNodeTypes.NodeTypeName == "CompendiumMapNode" select dbNodeTypes;
                    var metadataTypes = from dbMetaDataTypes in mappingDb.MetadataTypes where dbMetaDataTypes.MetadataTypeName == "string" select dbMetaDataTypes;
                    var domains = from dbDomain in mappingDb.Domains where dbDomain.DomainUid == domainId select dbDomain;

                    if (mapNodeTypes.Count() == 1 && metadataTypes.Count() == 1 && domains.Count() == 1) //there should only be one
                    {
                        Domain domain = domains.First();
                        NodeType nodeType = mapNodeTypes.First();
                        MetadataType metadataType = metadataTypes.First();

                        SoapMetadataType soapMetadataType = new SoapMetadataType();
                        soapMetadataType.Id = metadataType.MetadataTypeUid;
                        soapMetadataType.Name = metadataType.MetadataTypeName;

                        mapNode = CreateNode(nodeType.NodeTypeUid, mapName);
                        UpdateMetadata(mappingDb, mapNode.NodeUid, Guid.Empty, null, "Name", mapName, soapMetadataType, mapNode);
                        domain.Nodes.Add(mapNode);
                        mappingDb.SubmitChanges();
                    }
                    if (mapNode != null)
                    {
                        newMapUid = mapNode.NodeUid;

                        Dictionary<string, SoapNodeType> soapNodeTypes;
                        Dictionary<string, SoapRelationshipType> soapRelTypes;
                        Dictionary<string, SoapMetadataType> soapMetaTypes;
                        Dictionary<string, SoapDescriptorType> soapDescTypes;
                        GetSoapTypes(out soapNodeTypes, out soapRelTypes, out soapMetaTypes, out soapDescTypes);

                        Guid domainNodeId = GetDomainNodeId(domainId);
                        ConnectToMap(domainId, domainNodeId, newMapUid, soapDescTypes, soapRelTypes);
                    }
                }
            });
            return newMapUid;
        }