00001 using System;
00002 using System.Collections;
00003 using System.Collections.Generic;
00004 using System.ComponentModel;
00005 using System.Reflection;
00006 using System.Resources;
00007 using System.Text.RegularExpressions;
00008 using System.Web;
00009 using N2.Integrity;
00010 using System.Diagnostics;
00011 using N2.Engine;
00012 using System.Threading;
00013
00014 namespace N2
00015 {
00019 public static class Utility
00020 {
00025 public static object Convert(object value, Type destinationType)
00026 {
00027 if (value != null)
00028 {
00029 TypeConverter destinationConverter = TypeDescriptor.GetConverter(destinationType);
00030 TypeConverter sourceConverter = TypeDescriptor.GetConverter(value.GetType());
00031 if (destinationConverter != null && destinationConverter.CanConvertFrom(value.GetType()))
00032 return destinationConverter.ConvertFrom(value);
00033 if (sourceConverter != null && sourceConverter.CanConvertTo(destinationType))
00034 return sourceConverter.ConvertTo(value, destinationType);
00035 if (destinationType.IsEnum && value is int)
00036 return Enum.ToObject(destinationType, (int)value);
00037 if (!destinationType.IsAssignableFrom(value.GetType()))
00038 return System.Convert.ChangeType(value, destinationType);
00039 }
00040 return value;
00041 }
00042
00047 public static T Convert<T>(object value)
00048 {
00049 return (T)Convert(value, typeof (T));
00050 }
00051
00055 public static object Evaluate(object item, string expression)
00056 {
00057 if (item == null) return null;
00058
00059 PropertyInfo info = item.GetType().GetProperty(expression);
00060 if (info != null)
00061 return info.GetValue(item, new object[0]);
00062 else if (expression.IndexOf('.') > 0)
00063 {
00064 int dotIndex = expression.IndexOf('.');
00065 object obj = Evaluate(item, expression.Substring(0, dotIndex));
00066 if (obj != null)
00067 return Evaluate(obj, expression.Substring(dotIndex + 1, expression.Length - dotIndex - 1));
00068 }
00069 return null;
00070 }
00071
00077 public static string Evaluate(object item, string expression, string format)
00078 {
00079 return string.Format(format, Evaluate(item, expression));
00080 }
00081
00085 public static Type TypeFromName(string name)
00086 {
00087 if (name == null) throw new ArgumentNullException("name");
00088
00089 Type t = Type.GetType(name);
00090 if(t == null)
00091 throw new N2Exception("Couldn't find any type with the name '{0}'", name);
00092 return t;
00093 }
00094
00099 public static void SetProperty(object instance, string propertyName, object value)
00100 {
00101 if (instance == null) throw new ArgumentNullException("instance");
00102 if (propertyName == null) throw new ArgumentNullException("propertyName");
00103
00104 Type instanceType = instance.GetType();
00105 PropertyInfo pi = instanceType.GetProperty(propertyName);
00106 if (pi == null)
00107 throw new N2Exception("No property '{0}' found on the instance of type '{1}'.", propertyName, instanceType);
00108 if(!pi.CanWrite)
00109 throw new N2Exception("The property '{0}' on the instance of type '{1}' does not have a setter.", propertyName, instanceType);
00110 if (value != null && !value.GetType().IsAssignableFrom(pi.PropertyType))
00111 value = Convert(value, pi.PropertyType);
00112 pi.SetValue(instance, value, new object[0]);
00113 }
00114
00119 public static object GetProperty(object instance, string propertyName)
00120 {
00121 if (instance == null) throw new ArgumentNullException("instance");
00122 if (propertyName == null) throw new ArgumentNullException("propertyName");
00123
00124 Type instanceType = instance.GetType();
00125 PropertyInfo pi = instanceType.GetProperty(propertyName);
00126
00127 if (pi == null)
00128 throw new N2Exception("No property '{0}' found on the instance of type '{1}'.", propertyName, instanceType);
00129
00130 return pi.GetValue(instance, null);
00131 }
00132
00136 public static IEnumerable<ContentItem> UpdateSortOrder(IEnumerable siblings)
00137 {
00138 List<ContentItem> updatedItems = new List<ContentItem>();
00139 int lastSortOrder = int.MinValue;
00140 foreach (ContentItem sibling in siblings)
00141 {
00142 if (sibling.SortOrder <= lastSortOrder)
00143 {
00144 sibling.SortOrder = ++lastSortOrder;
00145 updatedItems.Add(sibling);
00146 }
00147 else
00148 lastSortOrder = sibling.SortOrder;
00149 }
00150 return updatedItems;
00151 }
00152
00158 public static void MoveToIndex(IList<ContentItem> siblings, ContentItem itemToMove, int newIndex)
00159 {
00160 siblings.Remove(itemToMove);
00161 siblings.Insert(newIndex, itemToMove);
00162 }
00163
00169 public static int Insert(ContentItem item, ContentItem newParent, string sortExpression)
00170 {
00171 return Insert(item, newParent, new Collections.ItemComparer(sortExpression));
00172 }
00173
00179 public static int Insert(ContentItem item, ContentItem newParent, IComparer<ContentItem> comparer)
00180 {
00181 if (item.Parent != null && item.Parent.Children.Contains(item))
00182 item.Parent.Children.Remove(item);
00183
00184 item.Parent = newParent;
00185 if (newParent != null)
00186 {
00187 if (IsDestinationBelowSource(item, newParent))
00188 {
00189 throw new DestinationOnOrBelowItselfException(item, newParent);
00190 }
00191
00192 IList<ContentItem> siblings = newParent.Children;
00193 for (int i = 0; i < siblings.Count; i++)
00194 {
00195 if (comparer.Compare(item, siblings[i]) < 0)
00196 {
00197 siblings.Insert(i, item);
00198 return i;
00199 }
00200 }
00201 siblings.Add(item);
00202 return siblings.Count - 1;
00203 }
00204 return -1;
00205 }
00206
00212 public static void Insert(ContentItem item, ContentItem newParent, int index)
00213 {
00214 if (item == null) throw new ArgumentNullException("item");
00215 if (newParent == null) throw new ArgumentNullException("newParent");
00216 if(index < 0 || index > newParent.Children.Count) throw new ArgumentOutOfRangeException("index");
00217
00218 if(item.Parent != null && item.Parent == newParent)
00219 {
00220 int previousIndex = newParent.Children.IndexOf(item);
00221 if (previousIndex < index)
00222 --index;
00223 MoveToIndex(item.Parent.Children, item, index);
00224 }
00225 else
00226 {
00227 if (item.Parent != null)
00228 item.Parent.Children.Remove(item);
00229 item.Parent = newParent;
00230 newParent.Children.Insert(index, item);
00231 }
00232 }
00233
00235 private static bool IsDestinationBelowSource(ContentItem source, ContentItem destination)
00236 {
00237 if(source == destination)
00238 return true;
00239 foreach(ContentItem ancestor in Find.EnumerateParents(destination))
00240 if (ancestor == source)
00241 return true;
00242 return false;
00243 }
00244
00249 public static string GetGlobalResourceString(string classKey, string resourceKey)
00250 {
00251 if (classKey != null && resourceKey != null && HttpContext.Current != null)
00252 {
00253 string cultureName = Thread.CurrentThread.CurrentUICulture.Name;
00254 ResourceKey key = new ResourceKey(classKey, resourceKey, cultureName);
00255 try
00256 {
00257 if (SingletonDictionary<ResourceKey, string>.Instance.ContainsKey(key))
00258 return SingletonDictionary<ResourceKey, string>.Instance[key];
00259
00260 return HttpContext.GetGlobalResourceObject(classKey, resourceKey) as string;
00261 }
00262 catch (MissingManifestResourceException)
00263 {
00264 SingletonDictionary<ResourceKey, string>.Instance[key] = null;
00265 }
00266 }
00267 return null;
00268 }
00269
00273 private class ResourceKey
00274 {
00275 readonly string classKey;
00276 readonly string resourceKey;
00277 readonly string cultureName;
00278
00279 public ResourceKey(string classKey, string resourceKey, string cultureName)
00280 {
00281 this.classKey = classKey ?? "";
00282 this.resourceKey = resourceKey ?? "";
00283 this.cultureName = cultureName ?? "";
00284 }
00285
00286 public override bool Equals(object obj)
00287 {
00288 ResourceKey other = obj as ResourceKey;
00289 return other != null
00290 && other.classKey == classKey
00291 && other.resourceKey == resourceKey
00292 && other.cultureName == cultureName;
00293 }
00294
00295 public override int GetHashCode()
00296 {
00297 unchecked
00298 {
00299 return classKey.GetHashCode()
00300 + resourceKey.GetHashCode()
00301 + cultureName.GetHashCode();
00302 }
00303 }
00304 }
00305
00309 public static string GetLocalResourceString(string resourceKey)
00310 {
00311 try
00312 {
00313 if (resourceKey != null && HttpContext.Current != null)
00314 {
00315 return HttpContext.GetLocalResourceObject(HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath, resourceKey) as string;
00316 }
00317 }
00318 catch (InvalidOperationException)
00319 {
00320 }
00321 catch (MissingManifestResourceException)
00322 {
00323 }
00324 catch (NullReferenceException)
00325 {
00326 }
00327 return null;
00328 }
00329
00334 public static string GetResourceString(string classKey, string resourceKey)
00335 {
00336 if(classKey != null)
00337 return GetGlobalResourceString(classKey, resourceKey) ?? GetLocalResourceString(resourceKey);
00338 else
00339 return GetLocalResourceString(resourceKey);
00340 }
00341
00342 public static Func<DateTime> CurrentTime = delegate { return DateTime.Now; };
00343
00344 [Obsolete("Moved to N2.Web.Url.ToAbsolute")]
00345 public static string ToAbsolute(string relativePath)
00346 {
00347 return N2.Web.Url.ToAbsolute(relativePath);
00348 }
00349
00355 public static void InvokeEvent(EventHandler<CancellableItemEventArgs> handler, ContentItem item, object sender, Action<ContentItem> finalAction)
00356 {
00357 if (handler != null && item.VersionOf == null)
00358 {
00359 CancellableItemEventArgs args = new CancellableItemEventArgs(item, finalAction);
00360
00361 handler.Invoke(sender, args);
00362
00363 if (!args.Cancel)
00364 args.FinalAction(args.AffectedItem);
00365 }
00366 else
00367 finalAction(item);
00368 }
00369
00377 public static ContentItem InvokeEvent(EventHandler<CancellableDestinationEventArgs> handler, object sender, ContentItem source, ContentItem destination, Func<ContentItem, ContentItem, ContentItem> finalAction)
00378 {
00379 if (handler != null && source.VersionOf == null)
00380 {
00381 CancellableDestinationEventArgs args = new CancellableDestinationEventArgs(source, destination, finalAction);
00382
00383 handler.Invoke(sender, args);
00384
00385 if (args.Cancel)
00386 return null;
00387
00388 return args.FinalAction(args.AffectedItem, args.Destination);
00389 }
00390
00391 return finalAction(source, destination);
00392 }
00393
00397 public static string GetTrail(ContentItem item)
00398 {
00399 if (item == null)
00400 return "/";
00401
00402 string ancestralTrail = item.AncestralTrail ?? GetTrail(item.Parent);
00403 return ancestralTrail + item.ID + "/";
00404 }
00405
00409 public static IEnumerable<Type> GetBaseTypes(Type type)
00410 {
00411 if (type == null || type.IsInterface || type.IsValueType)
00412 return new Type[0];
00413
00414 return GetBaseTypesAndSelf(type.BaseType);
00415 }
00416
00420 public static IEnumerable<Type> GetBaseTypesAndSelf(Type type)
00421 {
00422 if (type == null || type.IsInterface || type.IsValueType)
00423 yield break;
00424
00425 while (type != null)
00426 {
00427 yield return type;
00428 type = type.BaseType;
00429 }
00430 }
00431
00436 internal static AspNetHostingPermissionLevel GetTrustLevel()
00437 {
00438 foreach (AspNetHostingPermissionLevel trustLevel in new[] { AspNetHostingPermissionLevel.Unrestricted, AspNetHostingPermissionLevel.High, AspNetHostingPermissionLevel.Medium, AspNetHostingPermissionLevel.Low, AspNetHostingPermissionLevel.Minimal })
00439 {
00440 try
00441 {
00442 new AspNetHostingPermission(trustLevel).Demand();
00443 }
00444 catch (System.Security.SecurityException)
00445 {
00446 continue;
00447 }
00448
00449 return trustLevel;
00450 }
00451
00452 return AspNetHostingPermissionLevel.None;
00453 }
00454
00455 static readonly Regex StripTagsExpression = new Regex("<!*[^<>]*>", RegexOptions.Multiline);
00460 public static string ExtractFirstSentences(string html, int maxLength)
00461 {
00462 if (string.IsNullOrEmpty(html)) return html;
00463
00464 html = StripTagsExpression.Replace(html, "");
00465 int separatorIndex = 0;
00466 for (int i = 0; i < html.Length && i < maxLength; i++)
00467 {
00468 switch (html[i])
00469 {
00470 case '.':
00471 case '!':
00472 case '?':
00473 separatorIndex = i;
00474 break;
00475 default:
00476 break;
00477 }
00478 }
00479
00480 if (separatorIndex == 0 && html.Length > 0)
00481 return html.Substring(0, Math.Min(html.Length, maxLength));
00482
00483 return html.Substring(0, separatorIndex + 1);
00484 }
00485
00486 internal static int InheritanceDepth(Type type)
00487 {
00488 if (type == null || type == typeof(object))
00489 return 0;
00490 return 1 + InheritanceDepth(type.BaseType);
00491 }
00492
00498 internal static T GetContentAdapter<T>(this IEngine engine, ContentItem item) where T:AbstractContentAdapter
00499 {
00500 return engine.Resolve<IContentAdapterProvider>().ResolveAdapter<T>(item);
00501 }
00502
00506 internal static IEngine Engine(this System.Web.UI.Page page)
00507 {
00508 var accessor = page as IProvider<IEngine>;
00509 if (accessor != null)
00510 return accessor.Get();
00511 else
00512 return N2.Context.Current;
00513 }
00514 }
00515 }