// Path: cliche-shell-core/src/main/java/com/maxifier/cliche/util/ArrayHashMultiMap.java
// public final class ArrayHashMultiMap<K, V> implements MultiMap<K, V> {
// 
//     private Map<K, List<V>> listMap;
// 
//     public ArrayHashMultiMap() {
//         listMap = new HashMap<K, List<V>>();
//     }
// 
//     public ArrayHashMultiMap(MultiMap<K, V> map) {
//         this();
//         putAll(map);
//     }
// 
//     public void put(K key, V value) {
//         List<V> values = listMap.get(key);
//         if (values == null) {
//             values = new ArrayList<V>();
//             listMap.put(key, values);
//         }
//         values.add(value);
//     }
// 
//     public Collection<V> get(K key) {
//         List<V> result = listMap.get(key);
//         if (result == null) {
//             result = new ArrayList<V>();
//         }
//         return result;
//     }
// 
//     public Set<K> keySet() {
//         return listMap.keySet();
//     }
// 
//     public void remove(K key, V value) {
//         List<V> values = listMap.get(key);
//         if (values != null) {
//             values.remove(value);
//             if (values.isEmpty()) {
//                 listMap.remove(key);
//             }
//         }
//     }
// 
//     public void removeAll(K key) {
//         listMap.remove(key);
//     }
// 
//     public int size() {
//         int sum = 0;
//         for (K key : listMap.keySet()) {
//             sum += listMap.get(key).size();
//         }
//         return sum;
//     }
// 
//     public void putAll(MultiMap<K, V> map) {
//         for (K key : map.keySet()) {
//             for (V val : map.get(key)) {
//                 put(key, val);
//             }
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return listMap.toString();
//     }
// 
// 
// 
// }
// 
// Path: cliche-shell-core/src/main/java/com/maxifier/cliche/util/MultiMap.java
// public interface MultiMap<K, V> {
// 
//     void put(K key, V value);
// 
//     void putAll(MultiMap<K, V> map);
// 
//     Collection<V> get(K key);
// 
//     Set<K> keySet();
// 
//     void remove(K key, V value);
// 
//     void removeAll(K key);
// 
//     /**
//      * @return total size of all value collections in the MultiMap.
//      */
//     int size();
//     
// }


import com.maxifier.cliche.util.ArrayHashMultiMap;
import com.maxifier.cliche.util.MultiMap;
import com.google.common.base.Strings;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/*
 * This file is part of the Cliche project, licensed under MIT License.
 * See LICENSE.txt file in root folder of Cliche sources.
 */

/*
 *   Introducing the asg.cliche (http://cliche.sourceforge.net/)
 * Cliche is to be a VERY simple reflection-based command line shell
 * to provide simple CLI for simple applications.
 * The name formed as follows: "CLI Shell" --> "CLIShe" --> "Cliche".
 */

package com.maxifier.cliche;





/**
 * Shell is the class interacting with user.
 * Provides the command loop.
 * All logic lies here.
 *
 * @author ASG
 */
public class Shell {

    public static String PROJECT_HOMEPAGE_URL = "http://cliche.sourceforge.net";

    private Output output;
    private Input input;
    private String appName;

    public static class Settings {
        private final Input input;
        private final Output output;
        private final MultiMap<String, Object> auxHandlers;
        private final boolean displayTime;

        public Settings(Input input, Output output, MultiMap auxHandlers, boolean displayTime) {
            this.input = input;
            this.output = output;
            this.auxHandlers = auxHandlers;
            this.displayTime = displayTime;
        }

        public Settings createWithAddedAuxHandlers(MultiMap<String, Object> addAuxHandlers) {
// Path: cliche-shell-core/src/main/java/com/maxifier/cliche/util/ArrayHashMultiMap.java
// public final class ArrayHashMultiMap<K, V> implements MultiMap<K, V> {
// 
//     private Map<K, List<V>> listMap;
// 
//     public ArrayHashMultiMap() {
//         listMap = new HashMap<K, List<V>>();
//     }
// 
//     public ArrayHashMultiMap(MultiMap<K, V> map) {
//         this();
//         putAll(map);
//     }
// 
//     public void put(K key, V value) {
//         List<V> values = listMap.get(key);
//         if (values == null) {
//             values = new ArrayList<V>();
//             listMap.put(key, values);
//         }
//         values.add(value);
//     }
// 
//     public Collection<V> get(K key) {
//         List<V> result = listMap.get(key);
//         if (result == null) {
//             result = new ArrayList<V>();
//         }
//         return result;
//     }
// 
//     public Set<K> keySet() {
//         return listMap.keySet();
//     }
// 
//     public void remove(K key, V value) {
//         List<V> values = listMap.get(key);
//         if (values != null) {
//             values.remove(value);
//             if (values.isEmpty()) {
//                 listMap.remove(key);
//             }
//         }
//     }
// 
//     public void removeAll(K key) {
//         listMap.remove(key);
//     }
// 
//     public int size() {
//         int sum = 0;
//         for (K key : listMap.keySet()) {
//             sum += listMap.get(key).size();
//         }
//         return sum;
//     }
// 
//     public void putAll(MultiMap<K, V> map) {
//         for (K key : map.keySet()) {
//             for (V val : map.get(key)) {
//                 put(key, val);
//             }
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return listMap.toString();
//     }
// 
// 
// 
// }
// 
// Path: cliche-shell-core/src/main/java/com/maxifier/cliche/util/MultiMap.java
// public interface MultiMap<K, V> {
// 
//     void put(K key, V value);
// 
//     void putAll(MultiMap<K, V> map);
// 
//     Collection<V> get(K key);
// 
//     Set<K> keySet();
// 
//     void remove(K key, V value);
// 
//     void removeAll(K key);
// 
//     /**
//      * @return total size of all value collections in the MultiMap.
//      */
//     int size();
//     
// }


// Path: cliche-shell-core/src/main/java/com/maxifier/cliche/Shell.java
import com.maxifier.cliche.util.ArrayHashMultiMap;
import com.maxifier.cliche.util.MultiMap;
import com.google.common.base.Strings;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/*
 * This file is part of the Cliche project, licensed under MIT License.
 * See LICENSE.txt file in root folder of Cliche sources.
 */

/*
 *   Introducing the asg.cliche (http://cliche.sourceforge.net/)
 * Cliche is to be a VERY simple reflection-based command line shell
 * to provide simple CLI for simple applications.
 * The name formed as follows: "CLI Shell" --> "CLIShe" --> "Cliche".
 */

package com.maxifier.cliche;





/**
 * Shell is the class interacting with user.
 * Provides the command loop.
 * All logic lies here.
 *
 * @author ASG
 */
public class Shell {

    public static String PROJECT_HOMEPAGE_URL = "http://cliche.sourceforge.net";

    private Output output;
    private Input input;
    private String appName;

    public static class Settings {
        private final Input input;
        private final Output output;
        private final MultiMap<String, Object> auxHandlers;
        private final boolean displayTime;

        public Settings(Input input, Output output, MultiMap auxHandlers, boolean displayTime) {
            this.input = input;
            this.output = output;
            this.auxHandlers = auxHandlers;
            this.displayTime = displayTime;
        }

        public Settings createWithAddedAuxHandlers(MultiMap<String, Object> addAuxHandlers) {
            MultiMap<String, Object> allAuxHandlers = new ArrayHashMultiMap<String, Object>(auxHandlers);