001package gu.dtalk;
002
003import java.io.ByteArrayOutputStream;
004import java.io.PrintStream;
005import java.io.UnsupportedEncodingException;
006import java.util.ArrayList;
007import java.util.Arrays;
008import java.util.Collections;
009import java.util.HashSet;
010import java.util.LinkedHashMap;
011import java.util.List;
012import java.util.Map;
013import java.util.Map.Entry;
014import java.util.Set;
015
016import com.alibaba.fastjson.TypeReference;
017import com.alibaba.fastjson.annotation.JSONField;
018import com.google.common.base.Function;
019import com.google.common.base.MoreObjects;
020import com.google.common.base.Predicate;
021import com.google.common.base.Predicates;
022import com.google.common.collect.Iterables;
023import com.google.common.collect.Lists;
024import com.google.common.collect.Sets;
025
026import static com.google.common.base.Preconditions.*;
027/**
028 * 多选列表选项
029 * @author guyadong
030 *
031 * @param <E>
032 */
033public class CheckOption<E> extends BaseOption<Set<Integer>> {
034        @JSONField(serialize = false,deserialize = false)
035        private final Predicate<Set<Integer>> checkValidator = new Predicate<Set<Integer>>() {
036
037                @Override
038                public boolean apply(Set<Integer> set) {
039                        boolean findInvalid = Iterables.tryFind(set, new Predicate<Integer>() {
040                                @Override
041                                public boolean apply(Integer index) {
042                                        return index < 0 || index >= options.size();
043                                }
044                        }).isPresent();
045                        return !findInvalid;
046                }
047        };
048        protected final LinkedHashMap<E, String> options = new LinkedHashMap<>();
049        public CheckOption() {
050                super(new TypeReference<Set<Integer>>() {}.getType());
051                super.setValidator(checkValidator);
052        }
053
054        public CheckOption<E> addOption(E opt,String desc){
055                options.put(checkNotNull(opt), MoreObjects.firstNonNull(desc, ""));
056                return this;
057        }
058
059        @Override
060        public OptionType getType() {
061                return OptionType.MULTICHECK;
062        }
063
064        @Override
065        public BaseOption<Set<Integer>> setValidator(Predicate<Set<Integer>> validator) {
066                return super.setValidator(Predicates.and(checkValidator, validator));
067        }
068
069        @JSONField(serialize = false,deserialize = false)
070        public List<E> getSelected(){
071                ArrayList<Integer> indexs = Lists.newArrayList((Set<Integer>) getValue());
072                final ArrayList<E> opts = Lists.newArrayList(options.keySet());
073                return Lists.transform(indexs, new Function<Integer, E>() {
074
075                        @Override
076                        public E apply(Integer input) {
077                                return opts.get(input);
078                        }
079                });
080        }
081        @JSONField(serialize = false,deserialize = false)
082        public CheckOption<E> setSelected(List<E> sel){
083                sel = MoreObjects.firstNonNull(sel, Collections.<E>emptyList());
084                Iterable<E> itor = Iterables.filter(sel, new Predicate<E>() {
085
086                        @Override
087                        public boolean apply(E input) {
088                                return options.containsKey(input);
089                        }
090                });
091                final ArrayList<E> opts = Lists.newArrayList(options.keySet());
092
093                HashSet<Integer> indexSet = Sets.newHashSet(Iterables.transform(itor, new Function<E,Integer>(){
094
095                        @Override
096                        public Integer apply(E input) {
097                                return opts.indexOf(input);
098                        }}));
099                setValue(indexSet);
100                return this;
101        }
102        @SuppressWarnings("unchecked")
103        public CheckOption<E> setSelected(E... sel){              
104                return setSelected(Arrays.asList(sel));         
105        }
106        public String contentOfOptions(){
107                ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
108                PrintStream stream = new PrintStream(bytestream);
109                int index=0;
110                stream.printf("\tavailable options:\n");
111                for(Entry<E, String> entry:options.entrySet()){
112                        String desc = entry.getValue();                 
113                        stream.printf("\t<%d>%s -- %s\n", index++,entry.getKey().toString(), desc.isEmpty() ? "NO DESC" : desc);
114                }
115                try {
116                        return new String(bytestream.toByteArray(),"utf-8");
117                } catch (UnsupportedEncodingException e) {
118                        throw new RuntimeException(e);
119                }
120        }
121
122        public Map<E, String> getOptions() {
123                return options;
124        }
125        public void setOptions(Map<E, String>  options) {
126                this.options.clear();
127                this.options.putAll(options);
128        }
129        public BaseOption<Set<Integer>> setValue(Integer ...selects){
130                return setValue(Sets.newHashSet(selects));
131        }
132}