     
     
     /// validate whether the setting name is valid (for a file name) and throw an error if not
-    func validate(settingName: String, originalName: String) throws {
+    final func validate(settingName: String, originalName: String) throws {
         
         // just case difference is OK
         guard settingName.caseInsensitiveCompare(originalName) != .orderedSame else { return }

    
    
    /// return a setting file URL in the user's Application Support domain (don't care if it exists)
    func preparedURLForUserSetting(name: String) -> URL {
        
        return self.userSettingDirectoryURL.appendingPathComponent(name).appendingPathExtension(self.filePathExtension)
    }
    
    
    /// whether the setting name is one of the bundled settings
    func isBundledSetting(name: String) -> Bool {
        
        return self.bundledSettingNames.contains(name)
    }
    
    
    /// whether the setting name is one of the bundled settings that is customized by user
    func isCustomizedBundledSetting(name: String) -> Bool {
        
        return self.isBundledSetting(name: name) && (self.urlForUserSetting(name: name) != nil)
    }
    
    
    /// return setting name appending number suffix without extension
    func savableSettingName(for proposedName: String, appendCopySuffix: Bool = false) -> String {
        
        let suffix = appendCopySuffix ? NSLocalizedString("copy", comment: "copied file suffix") : nil
        

    
    
    /// duplicate the setting with name
    final func duplicateSetting(name: String) throws {
        
        let newName = self.savableSettingName(for: name, appendCopySuffix: true)
        
