Resolution.cs
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license.
4 //
5 // Microsoft Bot Framework: http://botframework.com
6 //
7 // Bot Builder SDK GitHub:
8 // https://github.com/Microsoft/BotBuilder
9 //
10 // Copyright (c) Microsoft Corporation
11 // All rights reserved.
12 //
13 // MIT License:
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 
34 using System;
35 using System.Collections.Generic;
36 using System.ComponentModel;
37 using System.IO;
38 using System.Linq;
39 using System.Text;
40 using System.Text.RegularExpressions;
41 using System.Web;
42 
43 namespace Microsoft.Bot.Builder.Luis
44 {
45  public abstract class Resolution
46  {
47  public override string ToString()
48  {
49  var builder = new StringBuilder();
50  var properties = this.GetType().GetProperties();
51  foreach (var property in properties)
52  {
53  var value = property.GetValue(this);
54  if (value != null)
55  {
56  if (builder.Length > 0)
57  {
58  builder.Append(",");
59  }
60  builder.Append(property.Name);
61  builder.Append("=");
62  builder.Append(value);
63  }
64  }
65 
66  return builder.ToString();
67  }
68  }
69 
70  public static partial class BuiltIn
71  {
72  public static partial class DateTime
73  {
74  public enum DayPart
75  {
76  [Description("morning")]
77  MO,
78  [Description("midday")]
79  MI,
80  [Description("afternoon")]
81  AF,
82  [Description("evening")]
83  EV,
84  [Description("night")]
85  NI
86  }
87 
88  public enum Reference
89  {
90  [Description("past")]
91  PAST_REF,
92  [Description("present")]
93  PRESENT_REF,
94  [Description("future")]
95  FUTURE_REF
96  }
97 
98 
99  [Serializable]
100  public sealed class DateTimeResolution : Resolution, IEquatable<DateTimeResolution>
101  {
102  public Reference? Reference { get; }
103 
104  public int? Year { get; }
105  public int? Month { get; }
106  public int? Day { get; }
107 
108  public int? Week { get; }
109  public DayOfWeek? DayOfWeek { get; }
110 
111  public DayPart? DayPart { get; }
112 
113  public int? Hour { get; }
114  public int? Minute { get; }
115  public int? Second { get; }
116 
118  Reference? reference = null,
119  int? year = null, int? month = null, int? day = null,
120  int? week = null, DayOfWeek? dayOfWeek = null,
121  DayPart? dayPart = null,
122  int? hour = null, int? minute = null, int? second = null
123  )
124  {
125  this.Reference = reference;
126  this.Year = year;
127  this.Month = month;
128  this.Day = day;
129  this.Week = week;
130  this.DayOfWeek = dayOfWeek;
131  this.DayPart = dayPart;
132  this.Hour = hour;
133  this.Minute = minute;
134  this.Second = second;
135  }
136 
137  public DateTimeResolution(System.DateTime dateTime)
138  {
139  this.Year = dateTime.Year;
140  this.Month = dateTime.Month;
141  this.Day = dateTime.Day;
142  this.Hour = dateTime.Hour;
143  this.Minute = dateTime.Minute;
144  this.Second = dateTime.Second;
145  }
146  public bool Equals(DateTimeResolution other)
147  {
148  return other != null
149  && this.Reference == other.Reference
150  && this.Year == other.Year
151  && this.Month == other.Month
152  && this.Day == other.Day
153  && this.Week == other.Week
154  && this.DayOfWeek == other.DayOfWeek
155  && this.DayPart == other.DayPart
156  && this.Hour == other.Hour
157  && this.Minute == other.Minute
158  && this.Second == other.Second;
159  }
160  public override bool Equals(object other)
161  {
162  return this.Equals(other as DateTimeResolution);
163  }
164  public override int GetHashCode()
165  {
166  throw new NotImplementedException();
167  }
168 
169  public const string PatternDate =
170  @"
171  (?:
172  (?<year>X+|\d+)
173  (?:
174  -
175  (?<weekM>W)?
176  (?<month>X+|\d+)
177  (?:
178  -
179  (?<weekD>W)?
180  (?<day>X+|\d+)
181  )?
182  )?
183  )
184  ";
185 
186  public const string PatternTime =
187  @"
188  (?:
189  T
190  (?:
191  (?<part>MO|MI|AF|EV|NI)
192  |
193  (?<hour>X+|\d+)
194  (?:
195  :
196  (?<minute>X+|\d+)
197  (?:
198  :
199  (?<second>X+|\d+)
200  )?
201  )?
202  )
203  )
204  ";
205 
206  public static readonly string Pattern = $"^({PatternDate}{PatternTime} | {PatternDate} | {PatternTime})$";
207  public const RegexOptions Options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace;
208  public static readonly Regex Regex = new Regex(Pattern, Options);
209 
210  private static int? ParseIntOrNull(Group group)
211  {
212  if (group.Success)
213  {
214  var text = group.Value;
215  int number;
216  if (int.TryParse(text, out number))
217  {
218  return number;
219  }
220  else if (text.Length > 0)
221  {
222  for (int index = 0; index < text.Length; ++index)
223  {
224  switch (text[index])
225  {
226  case 'X':
227  case 'x':
228  continue;
229  default:
230  throw new NotImplementedException();
231  }
232  }
233 
234  // -1 means some variable X rather than missing "null" or specified constant value
235  return -1;
236  }
237  }
238 
239  return null;
240  }
241 
242  private static E? ParseEnumOrNull<E>(Group group) where E : struct
243  {
244  if (group.Success)
245  {
246  var text = group.Value;
247  E result;
248  if (Enum.TryParse<E>(text, out result))
249  {
250  return result;
251  }
252  }
253 
254  return null;
255  }
256 
257  private static readonly IReadOnlyDictionary<string, Reference> ReferenceByText
258  = new Dictionary<string, Reference>(StringComparer.OrdinalIgnoreCase)
259  {
260  { "PAST_REF", DateTime.Reference.PAST_REF },
261  { "PRESENT_REF", DateTime.Reference.PRESENT_REF },
262  { "FUTURE_REF", DateTime.Reference.FUTURE_REF },
263  };
264 
265  public static bool TryParse(string text, out DateTimeResolution resolution)
266  {
267  DateTime.Reference reference;
268  if (ReferenceByText.TryGetValue(text, out reference))
269  {
270  resolution = new DateTimeResolution(reference);
271  return true;
272  }
273 
274  var match = Regex.Match(text);
275  if (match.Success)
276  {
277  var groups = match.Groups;
278  bool weekM = groups["weekM"].Success;
279  bool weekD = weekM || groups["weekD"].Success;
280 
281  resolution = new DateTimeResolution
282  (
283  year: ParseIntOrNull(groups["year"]),
284  week: weekM ? ParseIntOrNull(groups["month"]) : null,
285  month: !weekM ? ParseIntOrNull(groups["month"]) : null,
286  dayOfWeek: weekD ? (DayOfWeek?)ParseIntOrNull(groups["day"]) : null,
287  day: !weekD ? ParseIntOrNull(groups["day"]) : null,
288  dayPart: ParseEnumOrNull<DayPart>(groups["part"]),
289  hour: ParseIntOrNull(groups["hour"]),
290  minute: ParseIntOrNull(groups["minute"]),
291  second: ParseIntOrNull(groups["second"])
292  );
293 
294  return true;
295  }
296 
297  resolution = null;
298  return false;
299  }
300  }
301 
302  public sealed class DurationResolution
303  {
304 
305  }
306  }
307  }
308 
309  public interface IResolutionParser
310  {
311  bool TryParse(IDictionary<string, string> properties, out Resolution resolution);
312  }
313 
314  public sealed class ResolutionParser : IResolutionParser
315  {
316  bool IResolutionParser.TryParse(IDictionary<string, string> properties, out Resolution resolution)
317  {
318  string resolution_type;
319  if (properties != null)
320  {
321  if (properties.TryGetValue("resolution_type", out resolution_type))
322  {
323  switch (resolution_type)
324  {
325  case "builtin.datetime.date":
326  string date;
327  if (properties.TryGetValue("date", out date))
328  {
330  if (BuiltIn.DateTime.DateTimeResolution.TryParse(date, out dateTime))
331  {
332  resolution = dateTime;
333  return true;
334  }
335  }
336 
337  break;
338  case "builtin.datetime.time":
339  case "builtin.datetime.set":
340  string time;
341  if (properties.TryGetValue("time", out time))
342  {
344  if (BuiltIn.DateTime.DateTimeResolution.TryParse(time, out dateTime))
345  {
346  resolution = dateTime;
347  return true;
348  }
349  }
350 
351  break;
352  }
353  }
354  }
355 
356  resolution = null;
357  return false;
358  }
359  }
360 }
static bool TryParse(string text, out DateTimeResolution resolution)
Definition: Resolution.cs:265
DateTimeResolution(Reference?reference=null, int?year=null, int?month=null, int?day=null, int?week=null, DayOfWeek?dayOfWeek=null, DayPart?dayPart=null, int?hour=null, int?minute=null, int?second=null)
Definition: Resolution.cs:117
bool TryParse(IDictionary< string, string > properties, out Resolution resolution)