<commit_before>package org.hamcrest.extras;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import org.hamcrest.*;

import static org.hamcrest.extras.Condition.matched;
import static org.hamcrest.extras.Condition.notMatched;

/**
* @author <NAME> 2012 http://www.hamcrest.com
*/
public class JsonPathMatcher extends TypeSafeDiagnosingMatcher<String> {
    private final String jsonPath;
    private Condition.Step<? super JsonObject, JsonElement> findElement;
    private Matcher<JsonElement> elementContents;

    public JsonPathMatcher(String jsonPath, Matcher<JsonElement> elementContents) {
        this.jsonPath = jsonPath;
        this.findElement = new FindElement(jsonPath);
        this.elementContents = elementContents;
    }

    @Override
    protected boolean matchesSafely(String source, Description mismatch) {
        return parse(source, mismatch)
                .and(findElement)
                .matches(elementContents);
    }


    public void describeTo(Description description) {
       description.appendText("Json with path '").appendText(jsonPath).appendText("'");
    }

    public static Matcher<String> hasJsonPath(final String jsonPath) {
        return new JsonPathMatcher(jsonPath, Matchers.any(JsonElement.class));
    }

    @SuppressWarnings("unchecked")
    public static Matcher<String> hasJsonElement(final String jsonPath, final Matcher<String> contentsMatcher) {
        return new JsonPathMatcher(jsonPath, elementWith(contentsMatcher, jsonPath));
    }


    private Condition<JsonObject> parse(String source, Description mismatch) {
        try {
            return matched(new JsonParser().parse(source).getAsJsonObject(), mismatch);
        } catch (JsonSyntaxException e) {
            mismatch.appendText(e.getMessage());
        }
        return notMatched();
    }

    private static Matcher<JsonElement> elementWith(Matcher<String> contentsMatcher, String jsonPath) {
        return new FeatureMatcher<JsonElement, String>(contentsMatcher, "element at " + jsonPath, "content") {
            @Override
            protected String featureValueOf(JsonElement actual) {
                return actual.getAsString();
            }
        };
    }

    private static class FindElement implements Condition.Step<JsonElement, JsonElement> {
        private final String jsonPath;

        public FindElement(String jsonPath) {
            this.jsonPath = jsonPath;
        }

        public Condition<JsonElement> apply(JsonElement root, Description mismatch) {
            Condition<JsonElement> current = matched(root, mismatch);
            for (String segment : jsonPath.split("\\.")) {
                current = current
                            .and(asObject(segment))
                            .and(nextSegment(segment));
            }
            return current;
        }
        
        private Condition.Step<JsonElement, JsonObject> asObject(final String segment) {
            return new Condition.Step<JsonElement, JsonObject>() {
                public Condition<JsonObject> apply(JsonElement element, Description mismatch) {
                    if (element.isJsonObject()) {
                        return matched(element.getAsJsonObject(), mismatch);
                    }
                    mismatch.appendText("no object at '").appendText(segment).appendText("'");
                    return notMatched();
                }
            };
        }
        private Condition.Step<JsonObject, JsonElement> nextSegment(final String segment) {
            return new Condition.Step<JsonObject, JsonElement>() {
                public Condition<JsonElement> apply(JsonObject object, Description mismatch) {
                    if (object.has(segment)) {
                        return matched(object.get(segment), mismatch);
                    }
                    mismatch.appendText("missing element '").appendText(segment).appendText("'");
                    return notMatched();
                }
            };
        }
    }
}
<commit_msg>using steps to navigate json path<commit_after>package org.hamcrest.extras;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import org.hamcrest.*;

import java.util.ArrayList;

import static org.hamcrest.extras.Condition.matched;
import static org.hamcrest.extras.Condition.notMatched;

/**
* @author <NAME> 2012 http://www.hamcrest.com
*/
public class JsonPathMatcher extends TypeSafeDiagnosingMatcher<String> {
    private final String jsonPath;
    private Condition.Step<? super JsonObject, JsonElement> findElement;
    private Matcher<JsonElement> elementContents;

    public JsonPathMatcher(String jsonPath, Matcher<JsonElement> elementContents) {
        this.jsonPath = jsonPath;
        this.findElement = new FindElement(jsonPath);
        this.elementContents = elementContents;
    }

    @Override
    protected boolean matchesSafely(String source, Description mismatch) {
        return parse(source, mismatch)
                .and(findElement)
                .matches(elementContents);
    }


    public void describeTo(Description description) {
       description.appendText("Json with path '").appendText(jsonPath).appendText("'");
    }

    public static Matcher<String> hasJsonPath(final String jsonPath) {
        return new JsonPathMatcher(jsonPath, Matchers.any(JsonElement.class));
    }

    @SuppressWarnings("unchecked")
    public static Matcher<String> hasJsonElement(final String jsonPath, final Matcher<String> contentsMatcher) {
        return new JsonPathMatcher(jsonPath, elementWith(contentsMatcher, jsonPath));
    }


    private Condition<JsonObject> parse(String source, Description mismatch) {
        try {
            return matched(new JsonParser().parse(source).getAsJsonObject(), mismatch);
        } catch (JsonSyntaxException e) {
            mismatch.appendText(e.getMessage());
        }
        return notMatched();
    }

    private static Matcher<JsonElement> elementWith(Matcher<String> contentsMatcher, String jsonPath) {
        return new FeatureMatcher<JsonElement, String>(contentsMatcher, "element at " + jsonPath, "content") {
            @Override
            protected String featureValueOf(JsonElement actual) {
                return actual.getAsString();
            }
        };
    }

    private static class FindElement implements Condition.Step<JsonElement, JsonElement> {
        private final String jsonPath;

        public FindElement(String jsonPath) {
            this.jsonPath = jsonPath;
        }

        public Condition<JsonElement> apply(JsonElement root, Description mismatch) {
            Condition<JsonElement> current = matched(root, mismatch);
            for (Segment segment : split(jsonPath)) {
                current = current.and(segment);
            }
            return current;
        }
    }
    
    private static Iterable<Segment> split(String jsonPath) {
        final ArrayList<Segment> segments = new ArrayList<Segment>();
        for (String pathSegment : jsonPath.split("\\.")) {
            segments.add(new Segment(pathSegment));
        }
        return segments;
    }

    private static class Segment implements Condition.Step<JsonElement, JsonElement> {
        private final String pathSegment;
        public Segment(String pathSegment) {
            this.pathSegment = pathSegment;
        }
        public Condition apply(JsonElement current, Description mismatch) {
            if (!current.isJsonObject()) {
                mismatch.appendText("no object at '").appendText(pathSegment).appendText("'");
                return notMatched();
            }
            JsonObject object = current.getAsJsonObject();
            if (!object.has(pathSegment)) {
                mismatch.appendText("missing element '").appendText(pathSegment).appendText("'");
                return notMatched();
            }
            return matched(object.get(pathSegment), mismatch);
        }
    }
}

{'fraction_non_alphanumeric': 0.09497481263054429, 'fraction_numerical': 0.000982921734856862, 'mean_word_length': 2.6242208370436333, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, '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': '4617131', 'n_tokens_mistral': 2057, 'n_tokens_neox': 1990, 'n_words': 463}