/// <summary> /// Extracts value from internal representation into final form /// </summary> /// <param name="info">Option for which to extract the value</param> /// <param name="knownSections">Dictionary of all known sections</param> /// <returns>Value in expected format</returns> private static object extractValue(OptionInfo info, Dictionary <QualifiedSectionName, InnerSection> knownSections) { // obtain section var qSec = info.Name.Section; if (!knownSections.ContainsKey(qSec)) { throw new ParserException( userMsg: "Error when retrieving expected value", developerMsg: "Error when finding internal representation of section of desired option, possibility of it being missing"); } var curSection = knownSections[qSec]; // option exists, retrieve value if (curSection.Options.ContainsKey(info.Name)) { var opt = curSection.Options[info.Name]; return(extractValue(info, opt)); } // option does not exist but is optional else if (info.IsOptional) { return(info.DefaultValue); } // option does not exist, and is missing else { throw new ParserException( userMsg: "Error when retrieving expected value", developerMsg: "Error when finding internal representation of section of desired option, possibility of it being missing"); } }
/// <summary> /// Checks whether given option exists and has appropriate comment, /// if it has no comment, it claims the default one /// </summary> /// <param name="option">Fully typed option info with, appropriate comment set</param> /// <param name="knownSections">Dictionary of all known sections</param> private static void checkOptionCommentAndSeen(OptionInfo option, Dictionary <QualifiedSectionName, InnerSection> knownSections) { var qSec = option.Name.Section; // only if section exists if (knownSections.ContainsKey(qSec)) { var innerSect = knownSections[qSec]; var qOpt = option.Name; // only if the option itself exists if (innerSect.Options.ContainsKey(qOpt)) { var innerOpt = innerSect.Options[qOpt]; // mark as seen for strict mode innerOpt.Seen = true; // only if it has no comment, default one is claimed if (innerOpt.Comment == null) { innerOpt.Comment = option.DefaultComment; } } } }
/// <summary> /// Set option info and it's value. /// NOTE: Only options which are set via this call can be ADDED into output (readed options are included automatically). /// </summary> /// <param name="info">Structure describing option format</param> /// <param name="value">Structure wearing option value</param> internal void SetOption(OptionInfo info, OptionValue value) { // Check inner constraints checkValidity(info, value); // obtain qNames QualifiedSectionName qSect = value.Name.Section; QualifiedOptionName qOpt = value.Name; // Check that section exists if (!knownSections.ContainsKey(qSect)) { throw new ParserException( userMsg: "error, unknown section", developerMsg: "tried to set option in unknown section, sections needs to be retrieved from RegisterStructure() or from the actual file"); } // Ensure option exists if (!knownSections[qSect].Options.ContainsKey(qOpt)) { InnerOption newOpt = new InnerOption(qOpt, null); knownSections[qSect].Options.Add(qOpt, newOpt); newOpt.Comment = info.DefaultComment; } // along the way, check the comment checkOptionCommentAndSeen(info, knownSections); // Pass value into option InnerOption curOpt = knownSections[qSect].Options[qOpt]; IValueConverter converter; try { converter = Converters.ConfigConverters.getConverter(info); } catch (Exception ex) { throw new ParserException(userMsg: "Error when deserializing value", developerMsg: "Unsupported value tried to be deserialized", inner: ex); } if (info.IsContainer) { curOpt.strValues.Clear(); foreach (var elem in ConfigRW.ConfigCreation.StructureFactory.GetContainerElements(value.ConvertedValue)) { curOpt.strValues.Add(converter.Serialize(elem)); } } else { curOpt.strValues.Clear(); curOpt.strValues.Add(converter.Serialize(value.ConvertedValue)); } }
/// <summary> /// Checks whether given option value satisfies given option constraints /// for single element (either the only one, or one from many if it is collection) /// </summary> /// <param name="info">Structure describing option format</param> /// <param name="value">Structure wearing option value</param> /// <param name="elem">Single element to be checkd</param> private static void checkValiditySingle(OptionInfo info, OptionValue value, object elem) { if ( (info.LowerBound != null && wrongOrder(info.LowerBound, elem)) || (info.UpperBound != null && wrongOrder(elem, info.UpperBound)) ) { throw new ParserExceptionWithinConfig( userMsg: "Value out of bounds for option '{1}::{2}'", developerMsg: "Given value is out of predefined bounds for option '{1}::{2}'", section: value.Name.Section.ID, option: value.Name.ID); } }
/// <summary> /// Checks whether given option value satisfies given option constraints /// </summary> /// <param name="info">Structure describing option format</param> /// <param name="value">Structure wearing option value</param> internal void checkValidity(OptionInfo info, OptionValue value) { // Container handling if (info.IsContainer) { foreach (var elem in ConfigRW.ConfigCreation.StructureFactory.GetContainerElements(value.ConvertedValue)) { checkValiditySingle(info, value, elem); } } // Scalar handling else { checkValiditySingle(info, value, value.ConvertedValue); } }
/// <summary> /// Extracts value from internal representation into final form /// internal representation existent and provided to the method /// </summary> /// <param name="info">Option for which to extract the value</param> /// <param name="opt">Inner representaiton of desired option with desired value</param> /// <returns>Value in expected format</returns> private static object extractValue(OptionInfo info, InnerOption opt) { // Check container/singleUnit consistenci if (!info.IsContainer && opt.strValues.Count > 1) { throw new ParserExceptionWithinConfig( userMsg: "Error when retrieving expected value for option '{1}::{2}' at line {0}", developerMsg: "internal representation contains more values, while desired is only one for option '{1}::{2}' at line {0}", line: opt.Line, option: info.Name.ID, section: info.Name.Section.ID ); } // Obtain converter IValueConverter convertor; try { convertor = Converters.ConfigConverters.getConverter(info); } catch (Exception ex) { throw new ParserExceptionWithinConfig( userMsg: "Cannot find convertor, possibly due to invalid type specified for option '{1}::{2}' at line {0}", developerMsg: "Convertor retrieving method thrown an exception, possibly due to invalid type specified for option '{1}::{2}' at line {0}", line: opt.Line, option: info.Name.ID, section: info.Name.Section.ID, inner: ex); } // Value extraction try { // Container if (info.IsContainer) { List <object> outElements = new List <object>(); foreach (string value in opt.strValues) { outElements.Add(convertor.Deserialize(value)); } return(ConfigRW.ConfigCreation.StructureFactory.CreateContainer(info, outElements)); } // Single value else { return(convertor.Deserialize(opt.strValues.Count > 0 ? opt.strValues[0] : "")); } } catch (Exception ex) { throw new ParserExceptionWithinConfig( userMsg: "Type conversion failed for container option '{1}::{2}' at line {0}", developerMsg: "An exception occurred during extraction of value from inner representaion for container option '{1}::{2}' at line {0}", line: opt.Line, option: info.Name.ID, section: info.Name.Section.ID, inner: ex); } }