Compare commits
	
		
			2 Commits
		
	
	
		
			7bf99a7390
			...
			43312c3362
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					43312c3362 | ||
| 
						 | 
					3890d27d7f | 
@ -7,9 +7,9 @@ root = true
 | 
				
			|||||||
#### Core EditorConfig Options ####
 | 
					#### Core EditorConfig Options ####
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Indentation and spacing
 | 
					# Indentation and spacing
 | 
				
			||||||
indent_size = 4
 | 
					indent_size = 3
 | 
				
			||||||
indent_style = tab
 | 
					indent_style = tab
 | 
				
			||||||
tab_width = 4
 | 
					tab_width = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# New line preferences
 | 
					# New line preferences
 | 
				
			||||||
end_of_line = crlf
 | 
					end_of_line = crlf
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Caching/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Caching/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Caching {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Caching.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Caching.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Collections/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Collections/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Collections {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Collections.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Collections.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Entities/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Entities/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Entities {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Entities.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Entities.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Hosting/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Hosting/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Hosting {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Hosting.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Hosting.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
using Connected.ServiceModel;
 | 
					using System.Collections;
 | 
				
			||||||
using System.Collections;
 | 
					 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Connected.Interop.Merging
 | 
					namespace Connected.Interop.Merging
 | 
				
			||||||
@ -11,7 +10,7 @@ namespace Connected.Interop.Merging
 | 
				
			|||||||
			if (destination is null || !HasSource(sources))
 | 
								if (destination is null || !HasSource(sources))
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var sourceProperties = AggregateProperties(sources);
 | 
								var sourceProperties = PropertyAggregator.Aggregate(sources);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			foreach (var property in Properties.GetImplementedProperties(destination))
 | 
								foreach (var property in Properties.GetImplementedProperties(destination))
 | 
				
			||||||
				MergeProperty(destination, sourceProperties, property);
 | 
									MergeProperty(destination, sourceProperties, property);
 | 
				
			||||||
@ -28,42 +27,6 @@ namespace Connected.Interop.Merging
 | 
				
			|||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private static Dictionary<string, object> AggregateProperties(params object[] sources)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			var result = new Dictionary<string, object>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (var i = sources.Length - 1; i >= 0; i--)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				var source = sources[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (source is null)
 | 
					 | 
				
			||||||
					continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				var props = Properties.GetImplementedProperties(source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				foreach (var property in props)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					if (result.ContainsKey(property.Name))
 | 
					 | 
				
			||||||
						continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					result.Add(property.Name, source);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (source is IPropertyProvider provider)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					foreach (var property in provider.Properties)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						if (result.ContainsKey(property.Key))
 | 
					 | 
				
			||||||
							continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						result.Add(property.Key, property.Value);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return result;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void MergeProperty(object destination, Dictionary<string, object> sourceProperties, PropertyInfo property)
 | 
							private void MergeProperty(object destination, Dictionary<string, object> sourceProperties, PropertyInfo property)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (property.PropertyType.IsTypePrimitive())
 | 
								if (property.PropertyType.IsTypePrimitive())
 | 
				
			||||||
@ -74,7 +37,8 @@ namespace Connected.Interop.Merging
 | 
				
			|||||||
				if (!sourceProperties.TryGetValue(property.Name, out object? source))
 | 
									if (!sourceProperties.TryGetValue(property.Name, out object? source))
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				property.SetValue(destination, source.GetType().GetProperty(property.Name).GetValue(source));
 | 
									if (source.GetType() is Type propertyType && PropertyResolver.Resolve(propertyType, property.Name) is PropertyInfo propertyInfo)
 | 
				
			||||||
 | 
										property.SetValue(destination, propertyInfo.GetValue(source));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else if (IsArray(property))
 | 
								else if (IsArray(property))
 | 
				
			||||||
				MergeEnumerable(destination, sourceProperties, property);
 | 
									MergeEnumerable(destination, sourceProperties, property);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								src/Connected.Interop/Merging/PropertyAggregator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/Connected.Interop/Merging/PropertyAggregator.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					using Connected.ServiceModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Connected.Interop.Merging;
 | 
				
			||||||
 | 
					internal static class PropertyAggregator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public static Dictionary<string, object> Aggregate(params object[] values)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							var result = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = values.Length - 1; i >= 0; i--)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (values[i] is not object value)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								foreach (var property in GetImplementedProperties(value))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (result.ContainsKey(property.Key))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									result.Add(property.Key, property.Value);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (value is IPropertyProvider provider)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									foreach (var property in provider.Properties)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if (result.ContainsKey(property.Key))
 | 
				
			||||||
 | 
											continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										result.Add(property.Key, property.Value);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static Dictionary<string, object> GetImplementedProperties(object value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (value is null)
 | 
				
			||||||
 | 
								return new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (value is object[] objectArray)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var result = new Dictionary<string, object>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (var i = objectArray.Length - 1; i >= 0; i--)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									var implementations = Properties.GetImplementedProperties(objectArray[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									foreach (var property in implementations)
 | 
				
			||||||
 | 
										result.Add(property.Name, objectArray[i]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var implementations = Properties.GetImplementedProperties(value);
 | 
				
			||||||
 | 
								var result = new Dictionary<string, object>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								foreach (var property in implementations)
 | 
				
			||||||
 | 
									result.Add(property.Name, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/Connected.Interop/Merging/PropertyResolver.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Connected.Interop/Merging/PropertyResolver.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Connected.Interop.Merging;
 | 
				
			||||||
 | 
					internal static class PropertyResolver
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public static PropertyInfo? Resolve(Type type, string propertyName)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (type.GetProperty(propertyName) is PropertyInfo property)
 | 
				
			||||||
 | 
								return property;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type.GetProperty(propertyName.ToCamelCase()) is PropertyInfo camelProperty)
 | 
				
			||||||
 | 
								return camelProperty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type.GetProperty(propertyName.ToPascalCase()) is PropertyInfo pascalProperty)
 | 
				
			||||||
 | 
								return pascalProperty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								src/Connected.Interop/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Interop/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Interop {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Interop.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Interop.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Net/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Net/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Net {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Net.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Net.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Security/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Security/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Security {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Security.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Security.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/Connected.Services/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Services/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Services {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Services.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Services.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
@ -51,4 +51,14 @@ public static class ServicesExtensions
 | 
				
			|||||||
		return (f is not null && type.GetInterface(f) is not null)
 | 
							return (f is not null && type.GetInterface(f) is not null)
 | 
				
			||||||
			|| (nf is not null && type.GetInterface(nf) is not null);
 | 
								|| (nf is not null && type.GetInterface(nf) is not null);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static string AsUrlFriendly(this string value)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return UrlGenerator.Generate(value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static string AsUrlFriendly(this string value, IEnumerable<string> existing)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return UrlGenerator.Generate(value, existing);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										112
									
								
								src/Connected.Services/UrlGenerator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/Connected.Services/UrlGenerator.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Connected.Services;
 | 
				
			||||||
 | 
					internal static class UrlGenerator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						private const string ValidCharacters = "abcdefghijklmnopqrstuvzxyw-";
 | 
				
			||||||
 | 
						private const string MinusReplacements = "_ .\t\r\n";
 | 
				
			||||||
 | 
						static UrlGenerator()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Replacements = new(StringComparer.OrdinalIgnoreCase)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								{"č", "c"},
 | 
				
			||||||
 | 
								{"š", "s"},
 | 
				
			||||||
 | 
								{"ž", "z"},
 | 
				
			||||||
 | 
								{"đ", "d"},
 | 
				
			||||||
 | 
								{"ć", "c"}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static Dictionary<string, string> Replacements { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static string Generate(string text)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (string.IsNullOrEmpty(text))
 | 
				
			||||||
 | 
								throw new NullReferenceException(nameof(text));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var result = new StringBuilder();
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Analyze each character.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							foreach (var s in text.Trim())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * If it's in a ValidCharacters collection that's fine, we just copy it
 | 
				
			||||||
 | 
								 * into the result.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (ValidCharacters.Contains(s, StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									result.Append(s);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * Look if it's in the MinusReplacements collection which means we'll
 | 
				
			||||||
 | 
								 * replace the character with the minus sign.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (MinusReplacements.Contains(s, StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									result.Append('-');
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * Last chance for the character to be included in the result is to 
 | 
				
			||||||
 | 
								 * resolve the hardcoded character replacements.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (Replacements.TryGetValue(s.ToString(), out var replacement))
 | 
				
			||||||
 | 
									result.Append(replacement);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * It's possible that no characters are included in the result. If that's
 | 
				
			||||||
 | 
							 * the case we are going to include an a character just for the sake of
 | 
				
			||||||
 | 
							 * being a valid string.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (result.Length == 0)
 | 
				
			||||||
 | 
								result.Append('a');
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Remove any redundant minus characters and we are done.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							var sb = new StringBuilder();
 | 
				
			||||||
 | 
							var active = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (var i = 0; i < result.Length; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (result[i] == '-')
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (active)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									active = true;
 | 
				
			||||||
 | 
									sb.Append(result[i]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									active = false;
 | 
				
			||||||
 | 
									sb.Append(result[i]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Remove trailing minus if exists.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return sb.ToString().Trim().Trim('-').ToLowerInvariant();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static string Generate(string text, IEnumerable<string> existing)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							var prepared = Generate(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!existing.Any())
 | 
				
			||||||
 | 
								return prepared;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var idx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (true)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var key = $"{prepared}-{idx}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!existing.Contains(key, StringComparer.OrdinalIgnoreCase))
 | 
				
			||||||
 | 
									return key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								idx++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								src/Connected.Threading/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Connected.Threading/SR.Designer.cs
									
									
									
										generated
									
									
									
								
							@ -39,7 +39,7 @@ namespace Connected.Threading {
 | 
				
			|||||||
        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
					        internal static global::System.Resources.ResourceManager ResourceManager {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                if (object.ReferenceEquals(resourceMan, null)) {
 | 
					                if (object.ReferenceEquals(resourceMan, null)) {
 | 
				
			||||||
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Server.Threading.SR", typeof(SR).Assembly);
 | 
					                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Connected.Threading.SR", typeof(SR).Assembly);
 | 
				
			||||||
                    resourceMan = temp;
 | 
					                    resourceMan = temp;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return resourceMan;
 | 
					                return resourceMan;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user