Fixing an issue with output parameters that are of type IntPtr
[castle.git] / MonoRail / Castle.MonoRail.Framework / Routing / BaseRoutingRuleContainer.cs
blobb061f7ff73a7cd1a3c7bd0cd9226279481378b26
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework.Routing
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Threading;
21 using Core;
23 /// <summary>
24 /// Pendent
25 /// </summary>
26 public class RoutingRuleContainer : IRoutingRuleContainer
28 private readonly List<DecoratedRule> rules = new List<DecoratedRule>();
29 private readonly Dictionary<string, IRoutingRule> name2Rule = new Dictionary<string, IRoutingRule>();
30 private readonly ReaderWriterLock locker = new ReaderWriterLock();
32 /// <summary>
33 /// Adds the specified rule.
34 /// </summary>
35 /// <param name="rule">The rule.</param>
36 public void Add(IRoutingRule rule)
38 // Lock for writing
39 rules.Add(new DecoratedRule(rule));
41 // For really fast access
42 if (rule.RouteName != null)
44 if (name2Rule.ContainsKey(rule.RouteName))
46 throw new InvalidOperationException("Attempt to register route with duplicated name: " + rule.RouteName);
49 name2Rule[rule.RouteName] = rule;
53 /// <summary>
54 /// Pendent
55 /// </summary>
56 public void Add(IRoutingRule rule, RouteAction action)
58 // Lock for writing
59 rules.Add(new DecoratedRule(rule, action));
62 /// <summary>
63 /// Creates the URL.
64 /// </summary>
65 /// <param name="routeName">Name of the route.</param>
66 /// <param name="hostname">The hostname.</param>
67 /// <param name="virtualPath">The virtual path.</param>
68 /// <param name="parameters">The parameters.</param>
69 /// <returns></returns>
70 public string CreateUrl(string routeName, string hostname, string virtualPath, IDictionary parameters)
72 // lock for reading
74 IRoutingRule rule;
76 if (!name2Rule.TryGetValue(routeName, out rule))
78 throw new MonoRailException("Could not find named route: " + routeName);
81 int points;
82 return rule.CreateUrl(hostname, virtualPath, parameters, out points);
85 /// <summary>
86 /// Pendent
87 /// </summary>
88 /// <param name="hostname">The hostname.</param>
89 /// <param name="virtualPath">The virtual path.</param>
90 /// <param name="parameters">The parameters.</param>
91 /// <returns></returns>
92 public string CreateUrl(string hostname, string virtualPath, IDictionary parameters)
94 int winnerPoints = 0;
95 string winnerUrl = null;
97 foreach(IRoutingRule rule in rules)
99 int points;
101 string url = rule.CreateUrl(hostname, virtualPath, parameters, out points);
103 if (url != null && points > winnerPoints)
105 winnerUrl = url;
106 winnerPoints = points;
110 return winnerUrl;
113 /// <summary>
114 /// Pendent
115 /// </summary>
116 /// <param name="hostname">The hostname.</param>
117 /// <param name="virtualPath">The virtual path.</param>
118 /// <param name="parameters">The parameters.</param>
119 /// <returns></returns>
120 public string CreateUrl(string hostname, string virtualPath, object parameters)
122 return CreateUrl(hostname, virtualPath, new ReflectionBasedDictionaryAdapter(parameters));
125 /// <summary>
126 /// Finds the match.
127 /// </summary>
128 /// <param name="url">The URL.</param>
129 /// <param name="context">The context.</param>
130 /// <returns></returns>
131 public RouteMatch FindMatch(string url, IRouteContext context)
133 // lock for reading
135 int winnerPoints = 0;
136 RouteMatch winner = null;
137 DecoratedRule winnerule = null;
139 foreach(DecoratedRule rule in rules)
141 RouteMatch match = new RouteMatch();
143 int points = rule.Matches(url, context, match);
145 if (points != 0 && points > winnerPoints)
147 winnerPoints = points;
148 winner = match;
149 winnerule = rule;
153 if (winner != null && winnerule.SelectionAction != null)
155 winnerule.SelectionAction(context, winner);
158 return winner;
161 /// <summary>
162 /// Gets a value indicating whether this container is empty.
163 /// </summary>
164 /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
165 public bool IsEmpty
167 get { return rules.Count == 0; }
170 class DecoratedRule : IRoutingRule
172 private readonly IRoutingRule inner;
173 private RouteAction selectionAction;
175 public DecoratedRule(IRoutingRule inner)
177 this.inner = inner;
180 public DecoratedRule(IRoutingRule inner, RouteAction selectionAction) : this(inner)
182 this.selectionAction = selectionAction;
185 public string CreateUrl(string hostname, string virtualPath, IDictionary parameters, out int points)
187 return inner.CreateUrl(hostname, virtualPath, parameters, out points);
190 public int Matches(string url, IRouteContext context, RouteMatch match)
192 return inner.Matches(url, context, match);
195 public string RouteName
197 get { return inner.RouteName; }
200 public RouteAction SelectionAction
202 get { return selectionAction; }