<commit_before>package com.github.rschmitt.dynamicobject;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static java.lang.String.format;
import static org.junit.Assert.assertEquals;

public class TaggedReaderTest {
    private static final String EDN = "{:dumb [#MyDumbClass{:version 1, :str \"str\"}]}";

    @Before
    public void setup() {
        DynamicObject.registerType(DumbClass.class, new DumbClassTranslator());
    }

    @After
    public void teardown() {
        DynamicObject.deregisterType(DumbClass.class);
    }

    @Test
    public void roundTrip() {
        DumbClassHolder holder = DynamicObject.deserialize(EDN, DumbClassHolder.class);

        String serialized = DynamicObject.serialize(holder);

        assertEquals(EDN, serialized);
        assertEquals(new DumbClass(1, "str"), holder.dumb().get(0));
    }

    @Test
    public void prettyPrint() {
        DumbClassHolder holder = DynamicObject.deserialize(EDN, DumbClassHolder.class);
        String expectedFormattedString = format("{:dumb [#MyDumbClass{:version 1, :str \"str\"}]}%n");
        assertEquals(expectedFormattedString, holder.toFormattedString());
    }
}

// This is a DynamicObject that contains a regular POJO.
interface DumbClassHolder extends DynamicObject<DumbClassHolder> {
    List<DumbClass> dumb();
}

// This is a translation class that functions as an Edn reader/writer for its associated POJO.
class DumbClassTranslator implements EdnTranslator<DumbClass> {
    @Override
    public DumbClass read(Object obj) {
        DumbClassProxy proxy = DynamicObject.wrap(obj, DumbClassProxy.class);
        return new DumbClass(proxy.version(), proxy.str());
    }

    @Override
    public String write(DumbClass obj) {
        return format("{:version %d, :str \"%s\"}", obj.getVersion(), obj.getStr());
    }

    @Override
    public String getTag() {
        return "MyDumbClass"; // This is deliberately different from the class name.
    }

    interface DumbClassProxy extends DynamicObject<DumbClassProxy> {
        long version();
        String str();
    }
}

// This is a POJO that has no knowledge of Edn.
class DumbClass {
    private final long version;
    private final String str;

    DumbClass(long version, String str) {
        this.version = version;<commit_msg>TaggedReaderTest: Use the proxy technique during serialization<commit_after>package com.github.rschmitt.dynamicobject;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static java.lang.String.format;
import static org.junit.Assert.assertEquals;

public class TaggedReaderTest {
    private static final String EDN = "{:dumb [#MyDumbClass{:version 1, :str \"str\"}]}";

    @Before
    public void setup() {
        DynamicObject.registerType(DumbClass.class, new DumbClassTranslator());
    }

    @After
    public void teardown() {
        DynamicObject.deregisterType(DumbClass.class);
    }

    @Test
    public void roundTrip() {
        DumbClassHolder holder = DynamicObject.deserialize(EDN, DumbClassHolder.class);

        String serialized = DynamicObject.serialize(holder);

        assertEquals(EDN, serialized);
        assertEquals(new DumbClass(1, "str"), holder.dumb().get(0));
    }

    @Test
    public void prettyPrint() {
        DumbClassHolder holder = DynamicObject.deserialize(EDN, DumbClassHolder.class);
        String expectedFormattedString = format("{:dumb [#MyDumbClass{:version 1, :str \"str\"}]}%n");
        assertEquals(expectedFormattedString, holder.toFormattedString());
    }
}

// This is a DynamicObject that contains a regular POJO.
interface DumbClassHolder extends DynamicObject<DumbClassHolder> {
    List<DumbClass> dumb();
}

// This is a translation class that functions as an Edn reader/writer for its associated POJO.
class DumbClassTranslator implements EdnTranslator<DumbClass> {
    @Override
    public DumbClass read(Object obj) {
        DumbClassProxy proxy = DynamicObject.wrap(obj, DumbClassProxy.class);
        return new DumbClass(proxy.version(), proxy.str());
    }

    @Override
    public String write(DumbClass obj) {
        DumbClassProxy proxy = DynamicObject.newInstance(DumbClassProxy.class);
        proxy = proxy.str(obj.getStr());
        proxy = proxy.version(obj.getVersion());
        return DynamicObject.serialize(proxy);
    }

    @Override
    public String getTag() {
        return "MyDumbClass"; // This is deliberately different from the class name.
    }

    interface DumbClassProxy extends DynamicObject<DumbClassProxy> {
        long version();
        String str();

        DumbClassProxy version(long version);
        DumbClassProxy str(String str);
    }
}

// This is a POJO that has no knowledge of Edn.
class DumbClass {
    private final long version;
    private final String str;

    DumbClass(long version, String str) {
        this.version = version;
{'fraction_non_alphanumeric': 0.10378879484079001, 'fraction_numerical': 0.0016122531237404273, 'mean_word_length': 3.4391771019677995, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '6036598', 'n_tokens_mistral': 1454, 'n_tokens_neox': 1406, 'n_words': 377}