// Path: common/src/main/java/eu/mikroskeem/shuriken/common/data/Pair.java
// public class Pair<K, V> {
//     private final K key;
//     private final V value;
// 
//     /**
//      * Construct a new pair
//      *
//      * @param key Pair key
//      * @param value Pair value
//      */
//     public Pair(K key, V value) {
//         this.key = key;
//         this.value = value;
//     }
// 
//     /**
//      * Gets pair key
//      *
//      * @return Pair key
//      */
//     public K getKey() {
//         return this.key;
//     }
// 
//     /**
//      * Gets pair value
//      *
//      * @return Pair value
//      */
//     public V getValue() {
//         return this.value;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (o == this) return true;
//         if (!(o instanceof Pair)) return false;
//         Pair other = (Pair) o;
//         return key == null ? other.getKey() == null : key.equals(other.getKey()) &&
//                 value == null ? other.getValue() == null : value.equals(other.getValue());
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = 1;
//         result = result * 59 + (key == null ? 43 : key.hashCode());
//         result = result * 59 + (value == null ? 43 : value.hashCode());
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         return "eu.mikroskeem.shuriken.common.data.Pair(key=" + this.getKey() + ", value=" + this.getValue() + ")";
//     }
// }
// 
// Path: instrumentation/src/main/java/eu/mikroskeem/shuriken/instrumentation/ClassTools.java
// public final class ClassTools {
//     /**
//      * Unqualify class name <br>
//      * In other words, <pre>foo.bar.baz</pre> -&gt; <pre>foo/bar/baz</pre>
//      *
//      * @param className Class name
//      * @return Unqualified class name
//      */
//     @NotNull
//     public static String unqualifyName(String className) {
//         return Ensure.notNull(className, "Class name shouldn't be null!").replace(".", "/");
//     }
// 
//     /**
//      * Unqualify class name
//      *
//      * @see #unqualifyName(String)
//      * @param clazz Class
//      * @return Unqualified class name
//      */
//     @NotNull
//     public static String unqualifyName(Class<?> clazz) {
//         return unqualifyName(Ensure.notNull(clazz, "Class shouldn't be null!").getName());
//     }
// 
//     /**
//      * Generate simple <pre>super()</pre> calling constructor
//      *
//      * @param classVisitor ClassVisitor instance
//      * @param superClass Super class name (use {@link Object} for non-extending classes
//      *                   (or explictly extending Object, which is redundant anyway)
//      */
//     public static void generateSimpleSuperConstructor(@NotNull ClassVisitor classVisitor, @NotNull String superClass) {
//         MethodVisitor mv = Ensure.notNull(classVisitor, "ClassWriter shouldn't be null!")
//                 .visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
//         mv.visitCode();
//         mv.visitVarInsn(ALOAD, 0);
//         mv.visitMethodInsn(INVOKESPECIAL, unqualifyName(superClass), "<init>", "()V", false);
//         mv.visitInsn(RETURN);
//         mv.visitMaxs(1, 0);
//         mv.visitEnd();
//     }
// 
//     /**
//      * Generate simple <pre>super()</pre> calling constructor
//      *
//      * @param classVisitor ClassWriter instance
//      * @param superClass Super class object (use {@link Object} for non-extending classes
//      *                   (or explictly extending Object, which is redundant anyway)
//      */
//     public static void generateSimpleSuperConstructor(@NotNull ClassVisitor classVisitor, @NotNull Class<?> superClass) {
//         generateSimpleSuperConstructor(classVisitor, Ensure.notNull(superClass, "Class shouldn't be null").getName());
//     }
// 
//     /**
//      * Formats class resource path from class name
//      *
//      * @param className Class name
//      * @return Resource path
//      */
//     @NotNull
//     public static String getClassResourcePath(@NotNull String className) {
//         return className.replace('.', '/').concat(".class");
//     }
// 
//     /**
//      * Formats class resource path from class object
//      *
//      * @param clazz Class
//      * @return Resource path
//      */
//     @NotNull
//     public static String getClassResourcePath(@NotNull Class<?> clazz) {
//         return getClassResourcePath(clazz.getName());
//     }
// }


import eu.mikroskeem.shuriken.common.data.Pair;
import eu.mikroskeem.shuriken.instrumentation.ClassTools;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_SUPER;
package eu.mikroskeem.test.shuriken.classloader;



/**
 * Generate test class
 *
 * @author Mark Vainomaa
 */
public class GenerateTestClass {
    public static Pair<String, byte[]> generate(){
        String className = "eu/mikroskeem/test/shuriken/classloader/classes/TestClass1";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
        cw.visit(52, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(Object.class), null);
        ClassTools.generateSimpleSuperConstructor(cw, Object.class);
        cw.visitEnd();
// Path: common/src/main/java/eu/mikroskeem/shuriken/common/data/Pair.java
// public class Pair<K, V> {
//     private final K key;
//     private final V value;
// 
//     /**
//      * Construct a new pair
//      *
//      * @param key Pair key
//      * @param value Pair value
//      */
//     public Pair(K key, V value) {
//         this.key = key;
//         this.value = value;
//     }
// 
//     /**
//      * Gets pair key
//      *
//      * @return Pair key
//      */
//     public K getKey() {
//         return this.key;
//     }
// 
//     /**
//      * Gets pair value
//      *
//      * @return Pair value
//      */
//     public V getValue() {
//         return this.value;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (o == this) return true;
//         if (!(o instanceof Pair)) return false;
//         Pair other = (Pair) o;
//         return key == null ? other.getKey() == null : key.equals(other.getKey()) &&
//                 value == null ? other.getValue() == null : value.equals(other.getValue());
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = 1;
//         result = result * 59 + (key == null ? 43 : key.hashCode());
//         result = result * 59 + (value == null ? 43 : value.hashCode());
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         return "eu.mikroskeem.shuriken.common.data.Pair(key=" + this.getKey() + ", value=" + this.getValue() + ")";
//     }
// }
// 
// Path: instrumentation/src/main/java/eu/mikroskeem/shuriken/instrumentation/ClassTools.java
// public final class ClassTools {
//     /**
//      * Unqualify class name <br>
//      * In other words, <pre>foo.bar.baz</pre> -&gt; <pre>foo/bar/baz</pre>
//      *
//      * @param className Class name
//      * @return Unqualified class name
//      */
//     @NotNull
//     public static String unqualifyName(String className) {
//         return Ensure.notNull(className, "Class name shouldn't be null!").replace(".", "/");
//     }
// 
//     /**
//      * Unqualify class name
//      *
//      * @see #unqualifyName(String)
//      * @param clazz Class
//      * @return Unqualified class name
//      */
//     @NotNull
//     public static String unqualifyName(Class<?> clazz) {
//         return unqualifyName(Ensure.notNull(clazz, "Class shouldn't be null!").getName());
//     }
// 
//     /**
//      * Generate simple <pre>super()</pre> calling constructor
//      *
//      * @param classVisitor ClassVisitor instance
//      * @param superClass Super class name (use {@link Object} for non-extending classes
//      *                   (or explictly extending Object, which is redundant anyway)
//      */
//     public static void generateSimpleSuperConstructor(@NotNull ClassVisitor classVisitor, @NotNull String superClass) {
//         MethodVisitor mv = Ensure.notNull(classVisitor, "ClassWriter shouldn't be null!")
//                 .visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
//         mv.visitCode();
//         mv.visitVarInsn(ALOAD, 0);
//         mv.visitMethodInsn(INVOKESPECIAL, unqualifyName(superClass), "<init>", "()V", false);
//         mv.visitInsn(RETURN);
//         mv.visitMaxs(1, 0);
//         mv.visitEnd();
//     }
// 
//     /**
//      * Generate simple <pre>super()</pre> calling constructor
//      *
//      * @param classVisitor ClassWriter instance
//      * @param superClass Super class object (use {@link Object} for non-extending classes
//      *                   (or explictly extending Object, which is redundant anyway)
//      */
//     public static void generateSimpleSuperConstructor(@NotNull ClassVisitor classVisitor, @NotNull Class<?> superClass) {
//         generateSimpleSuperConstructor(classVisitor, Ensure.notNull(superClass, "Class shouldn't be null").getName());
//     }
// 
//     /**
//      * Formats class resource path from class name
//      *
//      * @param className Class name
//      * @return Resource path
//      */
//     @NotNull
//     public static String getClassResourcePath(@NotNull String className) {
//         return className.replace('.', '/').concat(".class");
//     }
// 
//     /**
//      * Formats class resource path from class object
//      *
//      * @param clazz Class
//      * @return Resource path
//      */
//     @NotNull
//     public static String getClassResourcePath(@NotNull Class<?> clazz) {
//         return getClassResourcePath(clazz.getName());
//     }
// }


// Path: classloader/src/test/java/eu/mikroskeem/test/shuriken/classloader/GenerateTestClass.java
import eu.mikroskeem.shuriken.common.data.Pair;
import eu.mikroskeem.shuriken.instrumentation.ClassTools;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_SUPER;

package eu.mikroskeem.test.shuriken.classloader;



/**
 * Generate test class
 *
 * @author Mark Vainomaa
 */
public class GenerateTestClass {
    public static Pair<String, byte[]> generate(){
        String className = "eu/mikroskeem/test/shuriken/classloader/classes/TestClass1";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
        cw.visit(52, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(Object.class), null);
        ClassTools.generateSimpleSuperConstructor(cw, Object.class);
        cw.visitEnd();
        return new Pair<>(className+".class.br", cw.toByteArray());