示例#1
0
        private void parseInnerSyntaxOfResponseTemplate(Dictionary<string, ParserItem> root, Dictionary<string, string> customVariables, List<ParserError> errors)
        {
            List<string> keys = new List<string>(root.Keys);
            ParserCompareDefinition pcd;
            foreach (string key in keys)
            {

                if (root[key].value is string)
                {
                    // find out the exact comparing definiton from the value and save it along so we will be able to compare with actual received JSON response
                    root[key] = parseCompareRules(root[key], customVariables, errors);
                    continue;
                }

                if (root[key].value is Dictionary<string, ParserItem>) // Dictionary type means that original JSON had an object at this position
                {
                    // call the same function recursively for the entire sub-node
                    parseInnerSyntaxOfResponseTemplate((Dictionary<string, ParserItem>)root[key].value, customVariables, errors);
                    continue;
                }

                if (root[key].value is List<ParserItem>) // List type means that original JSON had an array at this position ...
                {
                    List<ParserItem> list = (List<ParserItem>)root[key].value;
                    if (list.Count > 0)
                    {
                        if (list[0].value is string) // if at least one item is present and it is string ...
                            root[key] = parseCompareRules(list[0], customVariables, errors); // ... parse compare rules for entire array from this field
                    }
                    continue;
                }

                // simple type
                // make parser compare definition for strict comparison and assingn it to this item
                pcd = new ParserCompareDefinition();
                pcd.value = root[key].value;
                root[key].comp_def = pcd;
            }
        }
示例#2
0
        private ParserItem parseCompareRules(ParserItem item, Dictionary<string, string> customVariables, List<ParserError> errors)
        {
            string value = (string)item.value;
            int original_error_count = errors.Count;

            // find out all positions of MAIN_SYNTAX_CHARACTERs in the string value
            List<int> occurrences = new List<int>();
            int index = 0;
            do
            {
                index = value.IndexOf(MAIN_SYNTAX_CHARACTER, index); // ... so, find all occurrences of function characters in given string value
                if (index != -1)
                {
                    if (index == 0 || value[index - 1] != ESCAPE_CHARACTER) // either first character or unescaped one
                        occurrences.Add(index);
                    index++;
                }
            } while (index != -1);
            List<int> original_occurrences = new List<int>(occurrences); // when we notify the user about parser error we want to refer to the positions from original template

            // take care of possibility that we got a plain string without any MAIN_SYNTAX_CHARACTERs
            if (occurrences.Count == 0)
            {
                item.comp_def = new ParserCompareDefinition();
                item.comp_def.type = typeof(string);
                item.comp_def.value = value;
                return item;
            }

            // take care of possible errors
            if (occurrences.Count < 5) // not enough MAIN_SYNTAX_CHARACTERs
                errors.Add(new ParserError(item.line, item.position + original_occurrences.Last(), string.Format(ERR_MSG_EXPECTING_CHARACTER, MAIN_SYNTAX_CHARACTER), SOURCE_TEMPLATE));
            if (occurrences.Count > 5) // too many MAIN_SYNTAX_CHARACTERs
                errors.Add(new ParserError(item.line, item.position + original_occurrences[5], string.Format(ERR_MSG_INVALID_CHARACTER, MAIN_SYNTAX_CHARACTER), SOURCE_TEMPLATE));
            if (occurrences.First() != 0) // illegal characters before first MAIN_SYNTAX_CHARACTER
                errors.Add(new ParserError(item.line, item.position, string.Format(ERR_MSG_INVALID_CHARACTER, value[0]), SOURCE_TEMPLATE));
            if (occurrences.Last() != value.Length - 1) // illegal characters after last MAIN_SYNTAX_CHARACTER
                errors.Add(new ParserError(item.line, item.position + original_occurrences.Last(), string.Format(ERR_MSG_INVALID_CHARACTER, value[original_occurrences.Last() + 1]), SOURCE_TEMPLATE));

            // if there are any new syntax errors we can't parse this item - return it without any change
            if (errors.Count > original_error_count)
                return item;

            // now  we can replace all escaped MAIN_SYNTAX_CHARACTER for the real ones
            // note: all concerned indices in occurrences list must be modified accordingly, since ESCAPE_CHARACTERs are being taken
            // out from the original string
            index = 0;
            do
            {
                index = value.IndexOf("" + ESCAPE_CHARACTER + MAIN_SYNTAX_CHARACTER, index); // find escaped MAIN_SYNTAX_CHARACTER
                if (index != -1)
                {
                    value = value.Remove(index, 1); // remove ESCAPE_CHARACTER from the string
                    // all occurrences with further placement than index of escaped character must be corrected by one
                    shift_occurrences(occurrences, index, -1);
                    index++;
                }
            } while (index != -1);

            //
            // retrieve individual values between MAIN_SYNTAX_CHARACTERs and save them to the item structure
            //
            string type = value.Substring(occurrences[0] + 1, occurrences[1] - occurrences[0] - 1); // type
            string[] ops = value.Substring(occurrences[1] + 1, occurrences[2] - occurrences[1] - 1).Split(new char[] {RESPONSE_OPERATION_SEPARATOR}, StringSplitOptions.RemoveEmptyEntries); // operation with possible modifiers
            string val = value.Substring(occurrences[2] + 1, occurrences[3] - occurrences[2] - 1); // value
            string var = value.Substring(occurrences[3] + 1, occurrences[4] - occurrences[3] - 1); // variable
            ParserCompareDefinition pcd = new ParserCompareDefinition();

            // type
            if (type.Length > 0)
            {
                switch (type)
                {
                    case RESPONSE_TYPE_STRING:
                        pcd.type = typeof(string);
                        break;
                    case RESPONSE_TYPE_INTEGER:
                        pcd.type = typeof(int);
                        break;
                    case RESPONSE_TYPE_FLOAT:
                        pcd.type = typeof(float);
                        break;
                    case RESPONSE_TYPE_BOOLEAN:
                        pcd.type = typeof(bool);
                        break;
                    case RESPONSE_TYPE_OBJECT:
                        pcd.type = typeof(object);
                        break;
                    case RESPONSE_TYPE_ARRAY:
                        pcd.type = typeof(Array);
                        break;
                    default: // urecognized type
                        errors.Add(new ParserError(item.line, item.position + 1, string.Format(ERR_MSG_UNKNOWN_TYPE, type), SOURCE_TEMPLATE));
                        break;
                }
            }

            // operation + modifiers
            bool use_var = false; // use variable modifier
            bool if_present = false; // if present modifier
            string op = null; // operation
            if (ops.Length > 0)
            {
                foreach (string ops_item in ops)
                {
                    switch (ops_item)
                    {
                        case RESPONSE_OPERATION_MODIFIER_USE_VARIABLE:
                            use_var = true;
                            break;
                        case RESPONSE_OPERATION_MODIFIER_IF_PRESENT:
                            if_present = true;
                            break;
                        case RESPONSE_OPERATION_EQUAL:
                            if (RESPONSE_OPERATION_EQUAL_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_NOT_EQUAL:
                            if (RESPONSE_OPERATION_NOT_EQUAL_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_LESS_THAN:
                            if (RESPONSE_OPERATION_LESS_THAN_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_LESS_THAN_OR_EQUAL:
                            if (RESPONSE_OPERATION_LESS_THAN_OR_EQUAL_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_GREATER_THAN:
                            if (RESPONSE_OPERATION_GREATER_THAN_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_GREATER_THAN_OR_EQUAL:
                            if (RESPONSE_OPERATION_GREATER_THAN_OR_EQUAL_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        case RESPONSE_OPERATION_MATCHING_REGEXP_PATTERN:
                            if (RESPONSE_OPERATION_MATCHING_REGEXP_PATTERN_ALLOWED_TYPES.Contains(type))
                                op = ops_item;
                            else
                                errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_OPERATION_DOESNT_SUPPORT_TYPE, ops_item, type), SOURCE_TEMPLATE));
                            break;
                        default: // urecognized operation type
                            errors.Add(new ParserError(item.line, item.position + original_occurrences[1] + 1, string.Format(ERR_MSG_UNKNOWN_OPERATION, ops_item), SOURCE_TEMPLATE));
                            break;
                    }
                }

                // assign operation and modifiers into parser compare definition object
                pcd.use_variable = use_var;
                pcd.if_present = if_present;
                pcd.operation = op;

                // if operation was specified, type must be also specified
                if (pcd.type == null && pcd.operation != null)
                    errors.Add(new ParserError(item.line, item.position + 1, ERR_MSG_MISING_TYPE_FOR_OPERATION, SOURCE_TEMPLATE));

            }

            // value
            if (val.Length > 0)
            {
                if (use_var) // do we want to replace variable name in value field by it's actual value?
                {
                    if (customVariables.ContainsKey(val)) // search for desired custom variable ...
                    {
                        // try to convert value of parsed variable name to desired type; if that is not possible add an error
                        pcd.value = convertToDesiredType(pcd.type, customVariables[val], item, errors, original_occurrences);
                    }
                    else // ... and add error if it doesn't exist
                        errors.Add(new ParserError(item.line, item.position + original_occurrences[2] + 1, string.Format(ERR_MSG_UNKNOWN_CUSTOM_VARIABLE, val), SOURCE_TEMPLATE));
                }
                else
                {
                    // try to convert parsed value to desired type; if that is not possible add an error
                    pcd.value = convertToDesiredType(pcd.type, val, item, errors, original_occurrences);
                }
            }
            else
            {
                // in case that every part of possible information from syntax string is missing, let's presume empty string
                if (occurrences[4] - occurrences[0] == 4)
                    pcd.value = "";
            }

            // variable
            if (var.Length > 0)
                pcd.var_name = var;

            // if there are any new syntax errors we can't parse this item - return it without any change
            if (errors.Count > original_error_count)
                return item;

            // assign newly constructed parser compare definition object into item and return the item
            item.comp_def = pcd;
            return item;
        }