/// <summary> /// Static constructor; Sets up the tag to type dictionary, as well as the auxiliary tag regex pattern /// </summary> static P4AuxiliaryTag() { TagNameToTypeMap = new Dictionary <String, Type>(); // Find all of the public types located in the executing assembly Type[] AssemblyTypes = Assembly.GetExecutingAssembly().GetExportedTypes(); foreach (Type CurType in AssemblyTypes) { // If one of the found types is a subclass of P4AuxiliaryTag and is not abstract, it should be added to // the regex pattern and the tag to type dictionary for future use if (CurType.IsSubclassOf(typeof(P4AuxiliaryTag)) && !CurType.IsAbstract) { try { // Instantiate a temporary instance of the relevant type and add it to the dictionary P4AuxiliaryTag CurTag = (P4AuxiliaryTag)Activator.CreateInstance(CurType); if (!TagNameToTypeMap.ContainsKey(CurTag.TagName)) { TagNameToTypeMap.Add(CurTag.TagName.ToLower(), CurType); } // Throw an exception if two different tags share the same tag name else { throw new Exception("Error: Auxiliary tag class " + CurType.Name + " has a tag name in common with another tag!"); } } // A default constructor is required for Activator.CreateInstance() to work as is, so throw a specific exception to warn // the user if it's not implemented catch (MissingMethodException E) { Console.WriteLine("The auxiliary tag class {0} lacks a required default constructor!\n{1}", CurType.Name, E.Message); } catch (Exception E) { Console.WriteLine("Exception raised while trying to instantiate potential auxiliary tags!\n{0}", E.Message); } } } // Construct the regex pattern for all valid auxiliary types by appending the name of every auxiliary type // from the dictionary into the pattern StringBuilder AuxStringBuilder = new StringBuilder(); // Append the tag pattern start AuxStringBuilder.Append(P4Tag.TagPatternStart); int TagNameIndex = 0; int NumTagNames = TagNameToTypeMap.Keys.Count; // Append each valid auxiliary type name foreach (String TagName in TagNameToTypeMap.Keys) { AuxStringBuilder.Append(TagName); // If not the last type in the dictionary, append an "|" character to the pattern if (TagNameIndex < NumTagNames - 1) { AuxStringBuilder.Append("|"); } ++TagNameIndex; } // Append the tag pattern end and set the auxiliary tag pattern to the result of the string builder AuxStringBuilder.Append(P4Tag.TagPatternEnd); AuxiliaryTagPattern = AuxStringBuilder.ToString(); }
/// <summary> /// Construct a P4ParsedSubchange with the provided start tag name and subchange string /// </summary> /// <param name="InStartTagName">Name/type of the start tag</param> /// <param name="InSubchangeString">String comprised of the rest of the subchange data</param> public P4ParsedSubchange(String InStartTagName, String InSubchangeString) { // Split the subchange string using the regex pattern for tags. This results in an array of items // consisting of [startTagDescription][tag][stringOfInfoForTag][tag][stringOfInfoForTag], etc. Regex TagSplitter = new Regex(P4Tag.GenericTagPattern, RegexOptions.IgnoreCase); String[] AuxiliaryTags = TagSplitter.Split(InSubchangeString); //Remove blank lines var NonEmptyAuxiliaryTags = new List <string>(); foreach (var Tag in AuxiliaryTags) { if (!string.IsNullOrEmpty(Tag)) { NonEmptyAuxiliaryTags.Add(Tag); } } AuxiliaryTags = NonEmptyAuxiliaryTags.ToArray(); // Split the possible description string on newlines to prevent the possibility of non-relevant junk being included as part // of the start description. String[] NewLineDelimiter = new String[] { "\n" }; String[] StartDescriptionArgs = AuxiliaryTags[0].Split(NewLineDelimiter, StringSplitOptions.RemoveEmptyEntries); // The first item in the split array should be the start tag's description; if it's a tag instead, use the empty string as the description (this case should be // validated against during submission) String StartDescription = !P4Tag.IsStringInTagFormat(StartDescriptionArgs[0]) ? StartDescriptionArgs[0].Trim() : String.Empty; mStartTag = new P4StartTag(InStartTagName, StartDescription); // Iterate through the array, constructing auxiliary tags as appropriate for (int AuxStringIndex = 0; AuxStringIndex < AuxiliaryTags.Length; ++AuxStringIndex) { String CurString = AuxiliaryTags[AuxStringIndex]; // Check if the current string is an auxiliary tag, and if so, if there's another non-tag string in the array after it. // If there is, it should be the string to use to populate the tag info from. if (P4AuxiliaryTag.IsStringAnAuxiliaryTag(CurString) && AuxStringIndex + 1 < AuxiliaryTags.Length && !P4Tag.IsStringInTagFormat(AuxiliaryTags[AuxStringIndex + 1])) { // Using the tag's name, try to find the correct type of auxiliary tag to use Type TagType = P4AuxiliaryTag.GetTagTypeFromString(CurString); if (TagType != null) { // Split the population string on new lines. The newly created tag will only utilize the part of the population string // that occurs before the first newline, eliminating the possibility of junk in between tags getting incorrectly put into // a valid tag. String[] TagArgs = AuxiliaryTags[++AuxStringIndex].Split(NewLineDelimiter, StringSplitOptions.RemoveEmptyEntries); // If the type was found, create a new instance of it and populate it from the population string P4AuxiliaryTag NewTag = (P4AuxiliaryTag)Activator.CreateInstance(TagType); if (NewTag != null && NewTag.PopulateFromString(TagArgs[0].Trim())) { // If one of these tag types already existed, add the new tag to the correct array in the dictionary if (mAuxiliaryTags.ContainsKey(CurString)) { mAuxiliaryTags[CurString].Add(NewTag); } // If this is the first occurrence of this kind of tag type, create a new array for it and put it in // the dictionary else { List <P4AuxiliaryTag> AuxTagList = new List <P4AuxiliaryTag>(); AuxTagList.Add(NewTag); mAuxiliaryTags.Add(CurString, AuxTagList); } } // Tell the user of a malformed tag, if the tag couldn't be constructed from the string else { Console.WriteLine("Encountered malformed tag of type {0}; not added to subchange.", CurString); } } } } }