2002-02-21 Gaurav Vaish <gvaish@iitk.ac.in>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / AdRotator.cs
index 52e66aca4c5b5d61e0c8136cc16c0e2a390e4f8d..f93f710f37b096743a2371b2977cab487eea2019 100755 (executable)
@@ -3,14 +3,23 @@
  * Class:     AdRotator\r
  * \r
  * Author:  Gaurav Vaish\r
+ * Maintainer: gvaish@iitk.ac.in\r
+ * Implementation: yes\r
  * Contact: <gvaish@iitk.ac.in>\r
- * Status:  10??%\r
+ * Status:  100%\r
  * \r
  * (C) Gaurav Vaish (2001)\r
  */\r
 \r
 using System;\r
+using System.IO;\r
 using System.Collections;\r
+using System.Collections.Specialized;\r
+using System.Web;\r
+using System.Web.Caching;\r
+using System.Web.UI;\r
+using System.Xml;\r
+using System.Web.Utils;\r
 \r
 namespace System.Web.UI.WebControls\r
 {\r
@@ -18,16 +27,206 @@ namespace System.Web.UI.WebControls
        {\r
 \r
                private string advertisementFile;\r
-               private string keywordFilter;\r
-               private string target;\r
+               private static readonly object AdCreatedEvent = new object();\r
 \r
-               public event AdCreatedEventHandler AdCreated;\r
+               // Will be set values during (On)PreRender-ing\r
+               private string alternateText;\r
+               private string imageUrl;\r
+               private string navigateUrl;\r
 \r
-               public AdRotator()\r
+               private string fileDirectory;\r
+\r
+               private class AdRecord\r
+               {\r
+                       public IDictionary adProps;\r
+                       public int         hits; // or impressions or clicks\r
+                       public string      keyword;\r
+\r
+                       public AdRecord(IDictionary adProps)\r
+                       {\r
+                               this.adProps = adProps;\r
+                               hits         = 0;\r
+                               keyword      = String.Empty;\r
+                       }\r
+               }\r
+\r
+/*\r
+ * Loading / Saving data from/to ad file and all the manipulations wrt to the URL...\r
+ * are incorporated by the following functions.\r
+ * GetData(string)\r
+ * LoadAdFile(string)\r
+ * IsAdMatching(AdRecord)\r
+ * ResolveAdUrl(string)\r
+ * SelectAd()\r
+ * The exact control flow will be detailed. Let me first write the functions\r
+ */\r
+\r
+               private AdRecord[] LoadAdFile(string file)\r
+               {\r
+                       Stream      fStream;\r
+                       ArrayList   list;\r
+                       XmlReader   reader;\r
+                       XmlDocument document;\r
+                       XmlNode     topNode, innerNode;\r
+                       IDictionary hybridDict = null;\r
+                       AdRecord[]  adsArray = null;\r
+                       try\r
+                       {\r
+                               fStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);\r
+                       } catch(Exception e)\r
+                       {\r
+                               throw new HttpException("AdRotator: Unable to open file");\r
+                       }\r
+                       try\r
+                       {\r
+                               list = new ArrayList();\r
+                               reader = new XmlTextReader(fStream);\r
+                               document = new XmlDocument();\r
+                               document.Load(reader);\r
+                               if(document.DocumentElement!=null)\r
+                               {\r
+                                       if(document.DocumentElement.LocalName=="Advertisements")\r
+                                       {\r
+                                               topNode = document.DocumentElement.FirstChild;\r
+                                               while(topNode!=null)\r
+                                               {\r
+                                                       if(topNode.LocalName=="Ad")\r
+                                                       {\r
+                                                               innerNode = topNode.FirstChild;\r
+                                                               while(innerNode!=null)\r
+                                                               {\r
+                                                                       if(innerNode.NodeType==XmlNodeType.Element)\r
+                                                                       {\r
+                                                                               if(hybridDict==null)\r
+                                                                               {\r
+                                                                                       hybridDict = new HybridDictionary();\r
+                                                                               }\r
+                                                                               hybridDict.Add(innerNode.LocalName, innerNode.InnerText);\r
+                                                                       }\r
+                                                                       innerNode = innerNode.NextSibling;\r
+                                                               }\r
+                                                               if(hybridDict!=null)\r
+                                                                       list.Add(hybridDict);\r
+                                                       }\r
+                                                       topNode = topNode.NextSibling;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               if(list.Count>0)\r
+                               {\r
+                                       adsArray = new AdRecord[list.Count];\r
+                                       for(int i=0; i < list.Count; i++)\r
+                                       {\r
+                                               adsArray[i] = new AdRecord((IDictionary)list[i]);\r
+                                       }\r
+                               }\r
+                       } catch(Exception e)\r
+                       {\r
+                               throw new HttpException("AdRotator_Parse_Error" + file);\r
+                       } finally\r
+                       {\r
+                               fStream.Close();\r
+                       }\r
+                       if(adsArray == null)\r
+                       {\r
+                               throw new HttpException("AdRotator_No_Advertisements_Found");\r
+                       }\r
+                       return adsArray;\r
+               }\r
+               \r
+               private AdRecord[] GetData(string file)\r
+               {\r
+                       string physPath = MapPathSecure(file);\r
+                       string AdKey = "AdRotatorCache: " + physPath;\r
+                       fileDirectory = UrlUtils.GetDirectory(UrlUtils.Combine(TemplateSourceDirectory, file));\r
+                       Cache cache = HttpRuntime.Cache;\r
+                       AdRecord[] records = (AdRecord[])cache[AdKey];\r
+                       if(records==null)\r
+                       {\r
+                               records = LoadAdFile(physPath);\r
+                               if(records==null)\r
+                               {\r
+                                       return null;\r
+                               }\r
+                               cache.Insert(AdKey, records, new CacheDependency(physPath));\r
+                       }\r
+                       return records;\r
+               }\r
+               \r
+               private IDictionary SelectAd()\r
+               {\r
+                       AdRecord[] records = GetData(AdvertisementFile);\r
+                       if(records!=null && records.Length!=0)\r
+                       {\r
+                               int impressions = 0;\r
+                               for(int i=0 ; i < records.Length; i++)\r
+                               {\r
+                                       if(IsAdMatching(records[i]))\r
+                                               impressions += records[1].hits;\r
+                               }\r
+                               if(impressions!=0)\r
+                               {\r
+                                       int rnd = (new Random()).Next(impressions) + 1;\r
+                                       int counter = 0;\r
+                                       int index = 0;\r
+                                       for(int i=0; i < records.Length; i++)\r
+                                       {\r
+                                               if(IsAdMatching(records[i]))\r
+                                               {\r
+                                                       if(rnd <= (counter + records[i].hits))\r
+                                                       {\r
+                                                               index = i;\r
+                                                               break;\r
+                                                       }\r
+                                                       counter += records[i].hits;\r
+                                               }\r
+                                       }\r
+                                       return records[index].adProps;\r
+                               }\r
+                       }\r
+                       return null;\r
+               }\r
+               \r
+               private bool IsAdMatching(AdRecord currAd)\r
+               {\r
+                       if(KeywordFilter!=String.Empty)\r
+                       {\r
+                               if(currAd.keyword.ToLower() == KeywordFilter.ToLower())\r
+                                       return false;\r
+                       }\r
+                       return true;\r
+               }\r
+               \r
+               private string ResolveAdUrl(string relativeUrl)\r
+               {\r
+                       if(relativeUrl.Length==0 || !UrlUtils.IsRelativeUrl(relativeUrl))\r
+                               return relativeUrl;\r
+                       string fullUrl = String.Empty;\r
+                       if(fileDirectory != null)\r
+                               fullUrl = fileDirectory;\r
+                       if(fullUrl.Length == 0)\r
+                               fullUrl = TemplateSourceDirectory;\r
+                       if(fullUrl.Length == 0)\r
+                               return relativeUrl;\r
+                       return (fullUrl + relativeUrl);\r
+               }\r
+               \r
+               public event AdCreatedEventHandler AdCreated\r
+               {\r
+                       add\r
+                       {\r
+                               Events.AddHandler(AdCreatedEvent, value);\r
+                       }\r
+                       remove\r
+                       {\r
+                               Events.RemoveHandler(AdCreatedEvent, value);\r
+                       }\r
+               }\r
+               \r
+               public AdRotator(): base()\r
                {\r
                        advertisementFile = string.Empty;\r
-                       keywordFilter     = string.Empty;\r
-                       target            = string.Empty;\r
+                       fileDirectory     = null;\r
                }\r
                \r
                public string AdvertisementFile\r
@@ -46,36 +245,84 @@ namespace System.Web.UI.WebControls
                {\r
                        get\r
                        {\r
-                               return keywordFilter;\r
+                               object o = ViewState["KeywordFilter"];\r
+                               if(o!=null)\r
+                                       return (string)o;\r
+                               return String.Empty;\r
                        }\r
                        set\r
                        {\r
-                               keywordFilter = value;\r
+                               if(value!=null)\r
+                                       ViewState["KeywordFilter"] = value.Trim();\r
                        }\r
                }\r
-               \r
+\r
                public string Target\r
                {\r
                        get\r
                        {\r
-                               return target;\r
+                               object o = ViewState["Target"];\r
+                               if(o!=null)\r
+                                       return (string)o;\r
+                               return String.Empty;\r
                        }\r
                        set\r
                        {\r
-                               target = value;\r
+                               ViewState["Target"] = value;\r
+                       }\r
+               }\r
+               \r
+               protected override ControlCollection CreateControlCollection()\r
+               {\r
+                       return new EmptyControlCollection(this);\r
+               }\r
+               \r
+               protected virtual void OnAdCreated(AdCreatedEventArgs e)\r
+               {\r
+                       if(Events!=null)\r
+                       {\r
+                               AdCreatedEventHandler aceh = (AdCreatedEventHandler)(Events[AdCreatedEvent]);\r
+                               if(aceh!=null)\r
+                                       aceh(this, e);\r
+                       }\r
+               }\r
+\r
+               protected override void OnPreRender(EventArgs e)\r
+               {\r
+                       if(AdvertisementFile!=String.Empty)\r
+                       {\r
+                               AdCreatedEventArgs acea = new AdCreatedEventArgs(SelectAd());\r
+                               imageUrl      = acea.ImageUrl;\r
+                               navigateUrl   = acea.NavigateUrl;\r
+                               alternateText = acea.AlternateText;\r
                        }\r
                }\r
                \r
                protected override void Render(HtmlTextWriter writer)\r
                {\r
                        HyperLink hLink = new HyperLink();\r
-                       Image     image;\r
-\r
-                       AttributeCollection attributeColl = base.Attributes;\r
-                       ICollection keys = attributeColl.Keys;\r
-                       IEnumerator iterator = keys.GetEnumerator();\r
-                       \r
-                       \r
+                       Image adImage = new Image();\r
+                       foreach(IEnumerable current in Attributes.Keys)\r
+                       {\r
+                               hLink.Attributes[(string)current] = Attributes[(string)current];\r
+                       }\r
+                       if(ID != null && ID.Length > 0)\r
+                               hLink.ID = ID;\r
+                       hLink.Target    = Target;\r
+                       hLink.AccessKey = AccessKey;\r
+                       hLink.Enabled   = Enabled;\r
+                       hLink.TabIndex  = TabIndex;\r
+                       hLink.RenderBeginTag(writer);\r
+                       if(ControlStyleCreated)\r
+                       {\r
+                               adImage.ApplyStyle(ControlStyle);\r
+                       }\r
+                       if(imageUrl!=null && imageUrl.Length > 0)\r
+                               adImage.ImageUrl = ResolveAdUrl(imageUrl);\r
+                       adImage.AlternateText = alternateText;\r
+                       adImage.ToolTip       = ToolTip;\r
+                       adImage.RenderControl(writer);\r
+                       hLink.RenderEndTag(writer);\r
                }\r
        }\r
 }\r