Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SchemaLookupTable.cs « SchemaObjectModel « EntityModel « Data « System « System.Data.Entity « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e6ea1117a1c8e274bd2c95d905b6a953209c4725 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//---------------------------------------------------------------------
// <copyright file="AliasResolver.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

namespace System.Data.EntityModel.SchemaObjectModel
{
    using System;
    using System.Collections.Generic;
    using System.Data.Metadata.Edm;
    using System.Diagnostics;

    /// <summary>
    /// Reponsible for keep map from alias to namespace for a given schema.
    /// </summary>
    internal sealed class AliasResolver
    {
        #region Fields
        private Dictionary<string, string> _aliasToNamespaceMap = new Dictionary<string, string>(StringComparer.Ordinal);
        private List<UsingElement> _usingElementCollection = new List<UsingElement>();
        private Schema _definingSchema;
        #endregion

        #region Public Methods
        /// <summary>
        /// Construct the LookUp table
        /// </summary>
        public AliasResolver(Schema schema)
        {
            _definingSchema = schema;

            // If there is an alias defined for the defining schema,
            // add it to the look up table
            if (!string.IsNullOrEmpty(schema.Alias))
            {
                _aliasToNamespaceMap.Add(schema.Alias, schema.Namespace);
            }
        }

        /// <summary>
        /// Add a ReferenceSchema to the table
        /// </summary>
        /// <param name="refSchema">the ReferenceSchema to add</param>
        public void Add(UsingElement usingElement)
        {
            Debug.Assert(usingElement != null, "usingElement parameter is null");

            string newNamespace = usingElement.NamespaceName;
            string newAlias = usingElement.Alias;

            // Check whether the alias is a reserved keyword
            if (CheckForSystemNamespace(usingElement, newAlias, NameKind.Alias))
            {
                newAlias = null;
            }

            //Check whether the namespace is a reserved keyword
            if (CheckForSystemNamespace(usingElement, newNamespace, NameKind.Namespace))
            {
                newNamespace = null;
            }

            // see if the alias has already been used
            if (newAlias != null && _aliasToNamespaceMap.ContainsKey(newAlias))
            {
                // it has, issue an error and make sure we don't try to add it
                usingElement.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.AliasNameIsAlreadyDefined(newAlias)); 
                newAlias = null;
            }

            // If there's an alias, add it.
            // Its okay if they add the same namespace twice, until they have different alias
            if (newAlias != null)
            {
                _aliasToNamespaceMap.Add(newAlias, newNamespace);
                _usingElementCollection.Add(usingElement);
            }
        }

        /// <summary>
        /// Get the Schema(s) a namespace or alias might refer to
        /// returned schemas may be null is called before or during Schema Resolution
        /// </summary>
        public bool TryResolveAlias(string alias, out string namespaceName)
        {
            Debug.Assert(!String.IsNullOrEmpty(alias), "alias must never be null");

            // Check if there is an alias defined with this name
            return _aliasToNamespaceMap.TryGetValue(alias, out namespaceName);
        }

        /// <summary>
        /// Resolves all the namespace specified in the using elements in this schema
        /// </summary>
        public void ResolveNamespaces()
        {
            foreach (UsingElement usingElement in _usingElementCollection)
            {
                if (!_definingSchema.SchemaManager.IsValidNamespaceName(usingElement.NamespaceName))
                {
                    usingElement.AddError(ErrorCode.InvalidNamespaceInUsing, EdmSchemaErrorSeverity.Error,
                        System.Data.Entity.Strings.InvalidNamespaceInUsing(usingElement.NamespaceName));
                }
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Check if the given name is a reserved keyword. if yes, add appropriate error to the refschema
        /// </summary>
        /// <param name="refSchema"></param>
        /// <param name="name"></param>
        /// <param name="nameKind"></param>
        /// <returns></returns>
        private bool CheckForSystemNamespace(UsingElement refSchema, string name, NameKind nameKind)
        {
            Debug.Assert(_definingSchema.ProviderManifest != null, "Since we don't allow using elements in provider manifest, provider manifest can never be null");

            // We need to check for system namespace
            if (EdmItemCollection.IsSystemNamespace(_definingSchema.ProviderManifest, name))
            {
                if (nameKind == NameKind.Alias)
                {
                    refSchema.AddError(ErrorCode.CannotUseSystemNamespaceAsAlias, EdmSchemaErrorSeverity.Error,
                        System.Data.Entity.Strings.CannotUseSystemNamespaceAsAlias(name));
                }
                else
                {
                    refSchema.AddError(ErrorCode.NeedNotUseSystemNamespaceInUsing, EdmSchemaErrorSeverity.Error,
                        System.Data.Entity.Strings.NeedNotUseSystemNamespaceInUsing(name));
                }
                return true;
            }
            return false;
        }
        #endregion

        #region Private Types
        /// <summary>
        /// Kind of Name
        /// </summary>
        private enum NameKind
        {
            /// <summary>It's an Alias</summary>
            Alias,
            /// <summary>It's a namespace</summary>
            Namespace,
        }
        #endregion
    }
}