Beispiel #1
0
        // If force==false, it actually means don't declare it at
        // the current level.
        public void ForceDeclaration(bool force)
        {
            VerifyIsEditable();

            if ((force == false) &&
                _flags[Flag_DeclarationRequired])
            {
                // Since it is required, we can not remove it
            }
            else
            {
                //
                //



                if (force == true && BaseConfigurationRecord.IsImplicitSection(SectionName))
                {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Cannot_declare_or_remove_implicit_section));
                }

                if (force == true && _flags[Flag_IsUndeclared])
                {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_cannot_edit_configurationsection_when_it_is_undeclared));
                }

                _flags[Flag_Declared] = force;
            }
        }
        //
        // Get a config section.
        //
        public object GetSection(string section, string configPath)
        {
            BaseConfigurationRecord configRecord = (BaseConfigurationRecord)GetUniqueConfigRecord(configPath);
            object result = configRecord.GetSection(section);

            return(result);
        }
Beispiel #3
0
        private SectionUpdates FindSectionUpdates(string configKey, bool isGroup)
        {
            string str;

            if (isGroup)
            {
                str = configKey;
            }
            else
            {
                string str2;
                BaseConfigurationRecord.SplitConfigKey(configKey, out str, out str2);
            }
            SectionUpdates updates = this;

            if (str.Length != 0)
            {
                foreach (string str3 in str.Split(BaseConfigurationRecord.ConfigPathSeparatorParams))
                {
                    SectionUpdates updates2 = (SectionUpdates)updates._groups[str3];
                    if (updates2 == null)
                    {
                        updates2 = new SectionUpdates(str3);
                        updates._groups[str3] = updates2;
                    }
                    updates = updates2;
                }
            }
            return(updates);
        }
Beispiel #4
0
        // If force==false, it actually means don't declare it at
        // the current level.
        public void ForceDeclaration(bool force)
        {
            VerifyIsEditable();

            if ((force == false) &&
                _flags[FlagDeclarationRequired])
            {
                // Since it is required, we can not remove it
            }
            else
            {
                // CONSIDER: There is no apriori way to determine if a section
                // is implicit or undeclared. Would it be better to simply
                // fail silently so that app code can easily loop through sections
                // and declare all of them?
                if (force && BaseConfigurationRecord.IsImplicitSection(SectionName))
                {
                    throw new ConfigurationErrorsException(SR.Cannot_declare_or_remove_implicit_section);
                }

                if (force && _flags[FlagIsUndeclared])
                {
                    throw new ConfigurationErrorsException(
                              SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
                }

                _flags[FlagDeclared] = force;
            }
        }
        private void RemoveConfigImpl(string configPath, BaseConfigurationRecord configRecord)
        {
            BaseConfigurationRecord record;

            if (!ConfigPathUtility.IsValid(configPath))
            {
                throw ExceptionUtil.ParameterInvalid("configPath");
            }
            string[] parts = ConfigPathUtility.GetParts(configPath);
            try
            {
                int num;
                this.AcquireHierarchyLockForWrite();
                this.hlFindConfigRecord(parts, out num, out record);
                if ((num != parts.Length) || ((configRecord != null) && !object.ReferenceEquals(configRecord, record)))
                {
                    return;
                }
                record.Parent.hlRemoveChild(parts[parts.Length - 1]);
            }
            finally
            {
                this.ReleaseHierarchyLockForWrite();
            }
            this.OnConfigRemoved(new InternalConfigEventArgs(configPath));
            record.CloseRecursive();
        }
Beispiel #6
0
        //
        // Find the SectionUpdates for a configKey, and create it if it does not exist.
        //
        private SectionUpdates FindSectionUpdates(string configKey, bool isGroup)
        {
            string group, dummy;

            if (isGroup)
            {
                group = configKey;
            }
            else
            {
                BaseConfigurationRecord.SplitConfigKey(configKey, out group, out dummy);
            }

            Debug.Assert(String.IsNullOrEmpty(_name), "FindSectionUpdates assumes search is from root record");
            SectionUpdates sectionUpdates = this;

            if (group.Length != 0)
            {
                // find the SectionUpdates for the group
                string [] groups = group.Split(BaseConfigurationRecord.ConfigPathSeparatorParams);
                foreach (string groupPart in groups)
                {
                    SectionUpdates sectionUpdatesChild = (SectionUpdates)sectionUpdates._groups[groupPart];
                    if (sectionUpdatesChild == null)
                    {
                        sectionUpdatesChild = new SectionUpdates(groupPart);
                        sectionUpdates._groups[groupPart] = sectionUpdatesChild;
                    }

                    sectionUpdates = sectionUpdatesChild;
                }
            }

            return(sectionUpdates);
        }
Beispiel #7
0
 internal void AssociateContext(BaseConfigurationRecord configRecord)
 {
     this._configRecord = configRecord;
     foreach (ConfigurationElement element in this.ConfigurationElements)
     {
         element.AssociateContext(this._configRecord);
     }
 }
Beispiel #8
0
        internal ContextInformation(BaseConfigurationRecord configRecord)
        {
            Debug.Assert(configRecord != null, "configRecord != null");

            _hostingContextEvaluated = false;
            _hostingContext          = null;
            _configRecord            = configRecord;
        }
Beispiel #9
0
        internal void SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord,
                                                         FactoryRecord factoryRecord, SectionRecord sectionRecord)
        {
            _flags[FlagAttached] = true;

            // factory info
            ConfigKey                            = factoryRecord.ConfigKey;
            Name                                 = factoryRecord.Name;
            _typeName                            = factoryRecord.FactoryTypeName;
            _allowDefinition                     = factoryRecord.AllowDefinition;
            _allowExeDefinition                  = factoryRecord.AllowExeDefinition;
            _flags[FlagAllowLocation]            = factoryRecord.AllowLocation;
            _flags[FlagRestartOnExternalChanges] = factoryRecord.RestartOnExternalChanges;
            _flags[FlagRequirePermission]        = factoryRecord.RequirePermission;
            _overrideModeDefault                 = factoryRecord.OverrideModeDefault;

            if (factoryRecord.IsUndeclared)
            {
                _flags[FlagIsUndeclared]        = true;
                _flags[FlagDeclared]            = false;
                _flags[FlagDeclarationRequired] = false;
            }
            else
            {
                _flags[FlagIsUndeclared]        = false;
                _flags[FlagDeclared]            = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, false) != null;
                _flags[FlagDeclarationRequired] = configRecord.IsRootDeclaration(factoryRecord.ConfigKey, false);
            }

            // section info
            _flags[FlagLocationLocked] = sectionRecord.Locked;
            _flags[FlagChildrenLocked] = sectionRecord.LockChildren;
            _flags[FlagChildrenLockWithoutFileInput] = sectionRecord.LockChildrenWithoutFileInput;

            if (sectionRecord.HasFileInput)
            {
                SectionInput fileInput = sectionRecord.FileInput;

                _flags[FlagProtectionProviderDetermined] = fileInput.IsProtectionProviderDetermined;
                _protectionProvider = fileInput.ProtectionProvider;

                SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo;

                _configSource                  = sectionXmlInfo.ConfigSource;
                ConfigSourceStreamName         = sectionXmlInfo.ConfigSourceStreamName;
                _overrideMode                  = sectionXmlInfo.OverrideModeSetting;
                _flags[FlagInheritInChildApps] = !sectionXmlInfo.SkipInChildApps;
                ProtectionProviderName         = sectionXmlInfo.ProtectionProviderName;
            }
            else
            {
                _flags[FlagProtectionProviderDetermined] = false;
                _protectionProvider = null;
            }

            // element context information
            _configurationSection.AssociateContext(configRecord);
        }
        internal void AssociateContext(BaseConfigurationRecord configRecord)
        {
            _configRecord = configRecord;

            // Associate with children
            foreach (ConfigurationElement currentElement in ConfigurationElements)
            {
                currentElement.AssociateContext(_configRecord);
            }
        }
Beispiel #11
0
 private void ValidatePropertyName(string name)
 {
     if (string.IsNullOrEmpty(name))
     {
         throw new ArgumentException(System.Configuration.SR.GetString("String_null_or_empty"), "name");
     }
     if (BaseConfigurationRecord.IsReservedAttributeName(name))
     {
         throw new ArgumentException(System.Configuration.SR.GetString("Property_name_reserved", new object[] { name }));
     }
 }
        public void Remove(string name)
        {
            this.VerifyIsAttachedToConfigRecord();
            this._configRecord.RemoveConfigurationSectionGroup(this._configSectionGroup.SectionGroupName, name);
            string key = BaseConfigurationRecord.CombineConfigKey(this._configSectionGroup.SectionGroupName, name);

            if (!this._configRecord.SectionFactories.Contains(key))
            {
                base.BaseRemove(name);
            }
        }
Beispiel #13
0
        private void ValidatePropertyName(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException(SR.String_null_or_empty, nameof(name));
            }

            if (BaseConfigurationRecord.IsReservedAttributeName(name))
            {
                throw new ArgumentException(SR.Format(SR.Property_name_reserved, name));
            }
        }
Beispiel #14
0
        // Remove the declaration and definition of a section in this config file, including any
        // location sections in the file. This will also remove any descendant sections and
        // section groups.
        //
        // Note that if the section group is declared in a parent, we still remove the declaration and
        // definition, and the instance of ConfigurationSectionGroup will be detached from the collection.
        // However, the collection will still have a ConfigurationSectionGroup of that name in the collection,
        // only it will have the value of the immediate parent.
        public void Remove(string name)
        {
            VerifyIsAttachedToConfigRecord();

            _configRecord.RemoveConfigurationSectionGroup(_configSectionGroup.SectionGroupName, name);

            // Remove the section from the collection if it is no longer in the list of all SectionGroupFactories.
            string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);

            if (!_configRecord.SectionFactories.Contains(configKey))
            {
                BaseRemove(name);
            }
        }
 void IInternalConfigRoot.Init(IInternalConfigHost host, bool isDesignTime)
 {
     this._host          = host;
     this._isDesignTime  = isDesignTime;
     this._hierarchyLock = new ReaderWriterLock();
     if (this._isDesignTime)
     {
         this._rootConfigRecord = MgmtConfigurationRecord.Create(this, null, string.Empty, null);
     }
     else
     {
         this._rootConfigRecord = (BaseConfigurationRecord)RuntimeConfigurationRecord.Create(this, null, string.Empty);
     }
 }
Beispiel #16
0
 internal void VerifyIsEditableFactory()
 {
     if ((this._configRecord != null) && this._configRecord.IsLocationConfig)
     {
         throw new InvalidOperationException(System.Configuration.SR.GetString("Config_cannot_edit_configurationsection_in_location_config"));
     }
     if (BaseConfigurationRecord.IsImplicitSection(this.ConfigKey))
     {
         throw new InvalidOperationException(System.Configuration.SR.GetString("Config_cannot_edit_configurationsection_when_it_is_implicit"));
     }
     if (this._flags[0x2000])
     {
         throw new InvalidOperationException(System.Configuration.SR.GetString("Config_cannot_edit_configurationsection_when_it_is_undeclared"));
     }
 }
Beispiel #17
0
        //
        // Find a config record.
        // If found, nextIndex == parts.Length and the resulting record is in currentRecord.
        // If not found, nextIndex is the index of the part of the path not found, and currentRecord
        // is the record that has been found so far (nexIndex - 1).
        //
        private void hlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord)
        {
            currentRecord = _rootConfigRecord;
            nextIndex     = 0;
            for (; nextIndex < parts.Length; nextIndex++)
            {
                BaseConfigurationRecord childRecord = currentRecord.hlGetChild(parts[nextIndex]);
                if (childRecord == null)
                {
                    break;
                }

                currentRecord = childRecord;
            }
        }
        public ConfigurationSectionGroup Get(string name)
        {
            this.VerifyIsAttachedToConfigRecord();
            if (string.IsNullOrEmpty(name))
            {
                throw ExceptionUtil.ParameterNullOrEmpty("name");
            }
            if (name.IndexOf('/') >= 0)
            {
                return(null);
            }
            string configKey = BaseConfigurationRecord.CombineConfigKey(this._configSectionGroup.SectionGroupName, name);

            return(this._configRecord.GetSectionGroup(configKey));
        }
        public IInternalConfigRecord GetUniqueConfigRecord(string configPath)
        {
            BaseConfigurationRecord configRecord = (BaseConfigurationRecord)this.GetConfigRecord(configPath);

            while (configRecord.IsEmpty)
            {
                BaseConfigurationRecord parent = configRecord.Parent;
                if (parent.IsRootConfig)
                {
                    return(configRecord);
                }
                configRecord = parent;
            }
            return(configRecord);
        }
 private void hlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord)
 {
     currentRecord = this._rootConfigRecord;
     nextIndex     = 0;
     while (nextIndex < parts.Length)
     {
         BaseConfigurationRecord record = currentRecord.hlGetChild(parts[nextIndex]);
         if (record == null)
         {
             return;
         }
         currentRecord = record;
         nextIndex++;
     }
 }
Beispiel #21
0
        void IInternalConfigRoot.Init(IInternalConfigHost host, bool isDesignTime)
        {
            _host          = host;
            _isDesignTime  = isDesignTime;
            _hierarchyLock = new ReaderWriterLock();

            // Dummy record to hold _children for root
            if (_isDesignTime)
            {
                _rootConfigRecord = MgmtConfigurationRecord.Create(this, null, string.Empty, null);
            }
            else
            {
                _rootConfigRecord = (BaseConfigurationRecord)RuntimeConfigurationRecord.Create(this, null, string.Empty);
            }
        }
Beispiel #22
0
 public void ForceDeclaration(bool force)
 {
     this.VerifyIsEditable();
     if (force || !this._flags[4])
     {
         if (force && BaseConfigurationRecord.IsImplicitSection(this.SectionName))
         {
             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Cannot_declare_or_remove_implicit_section"));
         }
         if (force && this._flags[0x2000])
         {
             throw new ConfigurationErrorsException(System.Configuration.SR.GetString("Config_cannot_edit_configurationsection_when_it_is_undeclared"));
         }
         this._flags[2] = force;
     }
 }
        // Remove the declaration and definition of a section in this config file, including any
        // location sections in the file.
        //
        // Note that if the section is declared in a parent, we still remove the declaration and
        // definition, and the instance of ConfigurationSection will be detached from the collection.
        // However, the collection will still have a ConfigurationSection of that name in the collection,
        // only it will have the value of the immediate parent.
        public void Remove(string name)
        {
            VerifyIsAttachedToConfigRecord();

            // Remove the factory and section from this record, so that when config is written,
            // it will contain neither a declaration or definition.
            _configRecord.RemoveConfigurationSection(_configSectionGroup.SectionGroupName, name);

            // Remove the section from the collection if it is no longer in the list of all SectionFactories.
            string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);

            if (!_configRecord.SectionFactories.Contains(configKey))
            {
                BaseRemove(name);
            }
        }
Beispiel #24
0
 internal void SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord)
 {
     this._flags[1]            = true;
     this._configKey           = factoryRecord.ConfigKey;
     this._group               = factoryRecord.Group;
     this._name                = factoryRecord.Name;
     this._typeName            = factoryRecord.FactoryTypeName;
     this._allowDefinition     = factoryRecord.AllowDefinition;
     this._allowExeDefinition  = factoryRecord.AllowExeDefinition;
     this._flags[8]            = factoryRecord.AllowLocation;
     this._flags[0x10]         = factoryRecord.RestartOnExternalChanges;
     this._flags[0x20]         = factoryRecord.RequirePermission;
     this._overrideModeDefault = factoryRecord.OverrideModeDefault;
     if (factoryRecord.IsUndeclared)
     {
         this._flags[0x2000] = true;
         this._flags[2]      = false;
         this._flags[4]      = false;
     }
     else
     {
         this._flags[0x2000] = false;
         this._flags[2]      = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, false) != null;
         this._flags[4]      = configRecord.IsRootDeclaration(factoryRecord.ConfigKey, false);
     }
     this._flags[0x40]   = sectionRecord.Locked;
     this._flags[0x80]   = sectionRecord.LockChildren;
     this._flags[0x4000] = sectionRecord.LockChildrenWithoutFileInput;
     if (sectionRecord.HasFileInput)
     {
         SectionInput fileInput = sectionRecord.FileInput;
         this._flags[0x800]       = fileInput.IsProtectionProviderDetermined;
         this._protectionProvider = fileInput.ProtectionProvider;
         SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo;
         this._configSource           = sectionXmlInfo.ConfigSource;
         this._configSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
         this._overrideMode           = sectionXmlInfo.OverrideModeSetting;
         this._flags[0x100]           = !sectionXmlInfo.SkipInChildApps;
         this._protectionProviderName = sectionXmlInfo.ProtectionProviderName;
     }
     else
     {
         this._flags[0x800]       = false;
         this._protectionProvider = null;
     }
     this._configurationSection.AssociateContext(configRecord);
 }
Beispiel #25
0
        internal void VerifyIsEditableFactory()
        {
            if ((_configRecord != null) && _configRecord.IsLocationConfig)
            {
                throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_in_location_config);
            }

            // Can't edit factory if the section is built-in
            if (BaseConfigurationRecord.IsImplicitSection(ConfigKey))
            {
                throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_implicit);
            }

            // Can't edit undeclared section
            if (_flags[FlagIsUndeclared])
            {
                throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
            }
        }
 public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation)
 {
     string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath);
     try
     {
         int num;
         BaseConfigurationRecord record;
         this.AcquireHierarchyLockForRead();
         this.hlFindConfigRecord(parts, out num, out record);
         if ((num == parts.Length) && object.ReferenceEquals(configRecord, record))
         {
             record.hlClearResultRecursive(configKey, forceEvaluation);
         }
     }
     finally
     {
         this.ReleaseHierarchyLockForRead();
     }
 }
Beispiel #27
0
        //
        // Get the nearest ancestor record (including self) which contains unique configuration information.
        //
        public IInternalConfigRecord GetUniqueConfigRecord(string configPath)
        {
            BaseConfigurationRecord configRecord = (BaseConfigurationRecord)GetConfigRecord(configPath);

            while (configRecord.IsEmpty)
            {
                BaseConfigurationRecord parentConfigRecord = configRecord.Parent;

                // If all config records are empty, return the immediate child of the
                // root placeholder (e.g. machine.config)
                if (parentConfigRecord.IsRootConfig)
                {
                    break;
                }

                configRecord = parentConfigRecord;
            }

            return(configRecord);
        }
        public ConfigurationSection Get(string name)
        {
            VerifyIsAttachedToConfigRecord();

            // validate name
            if (string.IsNullOrEmpty(name))
            {
                throw ExceptionUtil.ParameterNullOrEmpty(nameof(name));
            }

            // prevent GetConfig from returning config not in this collection
            if (name.IndexOf('/') >= 0)
            {
                return(null);
            }

            // get the section from the config record
            string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);

            return((ConfigurationSection)_configRecord.GetSection(configKey));
        }
        public ConfigurationSectionGroup Get(string name)
        {
            VerifyIsAttachedToConfigRecord();

            // validate name
            if (string.IsNullOrEmpty(name))
            {
                throw ExceptionUtil.ParameterNullOrEmpty(nameof(name));
            }

            // prevent GetConfig from returning config not in this collection
            if (name.IndexOf('/') >= 0) // string.Contains(char) is .NetCore2.1+ specific
            {
                return(null);
            }

            // get the section group
            string configKey = BaseConfigurationRecord.CombineConfigKey(_configSectionGroup.SectionGroupName, name);

            return(_configRecord.GetSectionGroup(configKey));
        }
Beispiel #30
0
        //
        // Clear the result of a configSection evaluation at a particular point
        // in the hierarchy.
        //
        public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation)
        {
            string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath);

            try {
                int index;
                BaseConfigurationRecord currentRecord;

                AcquireHierarchyLockForRead();

                hlFindConfigRecord(parts, out index, out currentRecord);

                // clear result only if configRecord it is still in the hierarchy
                if (index == parts.Length && Object.ReferenceEquals(configRecord, currentRecord))
                {
                    currentRecord.hlClearResultRecursive(configKey, forceEvaluation);
                }
            }
            finally {
                ReleaseHierarchyLockForRead();
            }
        }
Beispiel #31
0
        // Clear the result of a configSection evaluation at a particular point
        // in the hierarchy.
        public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation)
        {
            string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath);

            try
            {
                int index;
                BaseConfigurationRecord currentRecord;

                AcquireHierarchyLockForRead();

                HlFindConfigRecord(parts, out index, out currentRecord);

                // clear result only if configRecord it is still in the hierarchy
                if ((index == parts.Length) && ReferenceEquals(configRecord, currentRecord))
                    currentRecord.HlClearResultRecursive(configKey, forceEvaluation);
            }
            finally
            {
                ReleaseHierarchyLockForRead();
            }
        }
Beispiel #32
0
 // Remove the config record and all its children for the config path.
 public void RemoveConfigRecord(BaseConfigurationRecord configRecord)
 {
     RemoveConfigImpl(configRecord.ConfigPath, configRecord);
 }
Beispiel #33
0
        // Find and remove the config record and all its children for the config path.
        // Optionally ensure the config record matches a desired config record.
        private void RemoveConfigImpl(string configPath, BaseConfigurationRecord configRecord)
        {
            if (!ConfigPathUtility.IsValid(configPath)) throw ExceptionUtil.ParameterInvalid("configPath");

            string[] parts = ConfigPathUtility.GetParts(configPath);

            BaseConfigurationRecord currentRecord;

            // search under exclusive writer lock
            try
            {
                int index;

                AcquireHierarchyLockForWrite();

                HlFindConfigRecord(parts, out index, out currentRecord);

                // Return if not found, or does not match the one we are trying to remove.
                if ((index != parts.Length) || ((configRecord != null) && !ReferenceEquals(configRecord, currentRecord)))
                    return;

                // Remove it from the hierarchy.
                currentRecord.Parent.HlRemoveChild(parts[parts.Length - 1]);
            }
            finally
            {
                ReleaseHierarchyLockForWrite();
            }

            OnConfigRemoved(new InternalConfigEventArgs(configPath));

            // Close the record. This is safe to do outside the lock.
            currentRecord.CloseRecursive();
        }
Beispiel #34
0
        // Find a config record.
        // If found, nextIndex == parts.Length and the resulting record is in currentRecord.
        // If not found, nextIndex is the index of the part of the path not found, and currentRecord
        // is the record that has been found so far (nexIndex - 1).
        private void HlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord)
        {
            currentRecord = RootConfigRecord;
            nextIndex = 0;
            for (; nextIndex < parts.Length; nextIndex++)
            {
                BaseConfigurationRecord childRecord = currentRecord.HlGetChild(parts[nextIndex]);
                if (childRecord == null)
                    break;

                currentRecord = childRecord;
            }
        }