<commit_before>package org.commcare.xml;

import org.commcare.suite.model.StackFrameStep;
import org.commcare.session.SessionFrame;
import org.javarosa.xml.ElementParser;
import org.javarosa.xml.util.InvalidStructureException;
import org.javarosa.xpath.XPathParseTool;
import org.javarosa.xpath.parser.XPathSyntaxException;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * @author ctsims
 */
class StackFrameStepParser extends ElementParser<StackFrameStep> {

    StackFrameStepParser(KXmlParser parser) {
        super(parser);
    }

    @Override
    public StackFrameStep parse() throws InvalidStructureException, IOException, XmlPullParserException {
        String operation = parser.getName();
        String value = parser.getAttributeValue(null, "value");

        switch (operation) {
            case "datum":
                String datumId = parser.getAttributeValue(null, "id");
                return parseValue(SessionFrame.STATE_UNKNOWN, datumId);
            case "rewind":
                return parseValue(SessionFrame.STATE_REWIND, null);
            case "mark":
                return parseValue(SessionFrame.STATE_MARK, null);
            case "command":
                return parseValue(SessionFrame.STATE_COMMAND_ID, null);
            case "query":
                return parseQuery(value);
            case "jump":
                return parseJump();
            default:
                throw new InvalidStructureException("<" + operation + "> is not a valid stack frame element!", this.parser);
        }
    }

    private StackFrameStep parseQuery(String value) throws InvalidStructureException, IOException, XmlPullParserException {
        String queryId = parser.getAttributeValue(null, "id");
        String url = parser.getAttributeValue(null, "value");
        try {
            new URL(url);
        } catch (MalformedURLException e) {
            String errorMsg = "<query> element has invalid 'value' attribute (" + url + ").";
            throw new InvalidStructureException(errorMsg, parser);
        }

        StackFrameStep step = null;
        try {
            step = new StackFrameStep(SessionFrame.STATE_QUERY_REQUEST, queryId, url, false);
        } catch (XPathSyntaxException e) {
            throw new InvalidStructureException("Invalid expression for stack frame step definition: " + value + ".\n" + e.getMessage(), parser);
        }
        while (nextTagInBlock("query")) {
            String tagName = parser.getName();
            if ("data".equals(tagName)) {
                String key = parser.getAttributeValue(null, "key");
                String ref = parser.getAttributeValue(null, "ref");
                try {
                    step.addExtra(key, XPathParseTool.parseXPath(ref));
                } catch (XPathSyntaxException e) {
                    String errorMessage = "'ref' value is not a valid xpath expression: " + ref;
                    throw new InvalidStructureException(errorMessage, this.parser);
                }
            }
        }
        return step;
    }

    private StackFrameStep parseJump() throws InvalidStructureException, IOException, XmlPullParserException {
        String id = parser.getAttributeValue(null, "id");
        StackFrameStep step = new StackFrameStep(SessionFrame.STATE_SMART_LINK, id, null);
        TextParser textParser = new TextParser(parser);
        nextTag("url");
        nextTag("text");
        step.addExtra("url", textParser.parse());
        return step;
    }

    private StackFrameStep parseValue(String type, String datumId) throws XmlPullParserException, IOException, InvalidStructureException {<commit_msg>use different constructor<commit_after>package org.commcare.xml;

import org.commcare.suite.model.StackFrameStep;
import org.commcare.session.SessionFrame;
import org.javarosa.xml.ElementParser;
import org.javarosa.xml.util.InvalidStructureException;
import org.javarosa.xpath.XPathParseTool;
import org.javarosa.xpath.parser.XPathSyntaxException;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * @author ctsims
 */
class StackFrameStepParser extends ElementParser<StackFrameStep> {

    StackFrameStepParser(KXmlParser parser) {
        super(parser);
    }

    @Override
    public StackFrameStep parse() throws InvalidStructureException, IOException, XmlPullParserException {
        String operation = parser.getName();
        String value = parser.getAttributeValue(null, "value");

        switch (operation) {
            case "datum":
                String datumId = parser.getAttributeValue(null, "id");
                return parseValue(SessionFrame.STATE_UNKNOWN, datumId);
            case "rewind":
                return parseValue(SessionFrame.STATE_REWIND, null);
            case "mark":
                return parseValue(SessionFrame.STATE_MARK, null);
            case "command":
                return parseValue(SessionFrame.STATE_COMMAND_ID, null);
            case "query":
                return parseQuery();
            case "jump":
                return parseJump();
            default:
                throw new InvalidStructureException("<" + operation + "> is not a valid stack frame element!", this.parser);
        }
    }

    private StackFrameStep parseQuery() throws InvalidStructureException, IOException, XmlPullParserException {
        String queryId = parser.getAttributeValue(null, "id");
        String url = parser.getAttributeValue(null, "value");
        try {
            new URL(url);
        } catch (MalformedURLException e) {
            String errorMsg = "<query> element has invalid 'value' attribute (" + url + ").";
            throw new InvalidStructureException(errorMsg, parser);
        }

        StackFrameStep step = new StackFrameStep(SessionFrame.STATE_QUERY_REQUEST, queryId, url);
        while (nextTagInBlock("query")) {
            String tagName = parser.getName();
            if ("data".equals(tagName)) {
                String key = parser.getAttributeValue(null, "key");
                String ref = parser.getAttributeValue(null, "ref");
                try {
                    step.addExtra(key, XPathParseTool.parseXPath(ref));
                } catch (XPathSyntaxException e) {
                    String errorMessage = "'ref' value is not a valid xpath expression: " + ref;
                    throw new InvalidStructureException(errorMessage, this.parser);
                }
            }
        }
        return step;
    }

    private StackFrameStep parseJump() throws InvalidStructureException, IOException, XmlPullParserException {
        String id = parser.getAttributeValue(null, "id");
        StackFrameStep step = new StackFrameStep(SessionFrame.STATE_SMART_LINK, id, null);
        TextParser textParser = new TextParser(parser);
        nextTag("url");
        nextTag("text");
        step.addExtra("url", textParser.parse());
        return step;
    }

    private StackFrameStep parseValue(String type, String datumId) throws XmlPullParserException, IOException, InvalidStructureException {
{'fraction_non_alphanumeric': 0.09487249794351522, 'fraction_numerical': 0.0005483959418700301, 'mean_word_length': 2.629353233830846, 'pattern_counts': {'":': 12, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4261116', 'n_tokens_mistral': 1882, 'n_tokens_neox': 1830, 'n_words': 443}