package org.yi.happy.archive;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.yi.happy.annotate.EntryPoint;

/**
 * The top level entry point that dispatches to the sub-commands.
 */
@EntryPoint
public class Main {
    private static final class Cmd {

        private final String name;
        private final Class<?> cls;

        public Cmd(String name, Class<?> cls) {
            this.name = name;
            this.cls = cls;
        }

        public String getName() {
            return name;
        }

        public Class<?> getCls() {
            return cls;
        }
    }

    private static final List<Cmd> cmds = Collections.unmodifiableList(Arrays
            .asList(

            new Cmd("file-get", FileStoreFileGetMain.class),

            new Cmd("block-put", FileStoreBlockPutMain.class),

            new Cmd("stream-get", FileStoreStreamGetMain.class),

            new Cmd("stream-put", FileStoreStreamPutMain.class),

            new Cmd("tag-get", FileStoreTagGetMain.class),

            new Cmd("tag-put", FileStoreTagPutMain.class),

            new Cmd("decode", DecodeBlockMain.class),

            new Cmd("encode", EncodeContentMain.class),

            new Cmd("verify", VerifyMain.class),

            new Cmd("index-search", IndexSearchMain.class),

            new Cmd("volume-get", VolumeGetMain.class),

            new Cmd("store-list", FileStoreListMain.class),

            new Cmd("build-image", BuildImageMain.class),

            new Cmd("index-volume", IndexVolumeMain.class),

            new Cmd("store-remove", StoreRemoveMain.class),

            new Cmd("backup-list", LocalCandidateListMain.class),

            new Cmd("make-index-db", MakeIndexDatabaseMain.class)
            ));

    /**
     * Run the given sub command, from the command line.
     * 
     * @param args
     *            the arguments
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        if (args.length < 1) {
            help();
            return;
        }

        for (Cmd cmd : cmds) {
            if (cmd.getName().equals(args[0])) {
                Method m = cmd.getCls().getMethod("main", args.getClass());
                String[] a = Arrays.copyOfRange(args, 1, args.length);
                m.invoke(null, (Object) a);
                return;
            }
        }

        help();
    }

    private static void help() {
        for (Cmd cmd : cmds) {
            System.out.println(cmd.getName());
        }
    }
}

@@ -303,22 +303,16 @@
  static 
-final 
 class Cm
@@ -497,32 +497,107 @@
 cls;%0A        %7D%0A%0A
+        public Cmd(String name) %7B%0A            this(name, null);%0A        %7D%0A%0A
         public S
@@ -723,174 +723,505 @@
   %7D%0A
-    %7D%0A%0A    private static final List%3CCmd%3E cmds = Collections.unmodifiableList(Arrays%0A            .asList(%0A%0A            new Cmd(%22file-get%22, FileStoreFileGetMain.class)
+%0A        public void run(String%5B%5D args) throws Exception %7B%0A            Method m = getCls().getMethod(%22main%22, args.getClass());%0A            m.invoke(null, (Object) args);%0A        %7D%0A    %7D%0A%0A    private static final List%3CCmd%3E cmds = Collections.unmodifiableList(Arrays%0A            .asList(%0A%0A            new Cmd(%22file-get%22) %7B%0A                @Override%0A                public void run(String%5B%5D args) throws Exception %7B%0A                    FileStoreFileGetMain.main(args);%0A                %7D%0A            %7D
 ,%0A%0A 
@@ -2592,84 +2592,8 @@
 ) %7B%0A
-                Method m = cmd.getCls().getMethod(%22main%22, args.getClass());%0A
     
@@ -2679,32 +2679,16 @@
     
-m.invoke(null, (Object) 
+cmd.run(
 a);%0A

allow for custom command invocation in main entry point, in preparation for more dependency injection.