001package org.maltparser.core.options.option;
002
003import java.util.Collections;
004import java.util.Formatter;
005import java.util.HashMap;
006import java.util.Map;
007import java.util.SortedSet;
008import java.util.TreeSet;
009
010import org.maltparser.core.exception.MaltChainedException;
011import org.maltparser.core.options.OptionException;
012import org.maltparser.core.options.OptionGroup;
013import org.maltparser.core.plugin.PluginLoader;
014
015/**
016 * A class type option is an option that can only contain string value that corresponds to a class. 
017 *
018 * @author Johan Hall
019 * @since 1.0
020**/
021public class ClassOption extends Option{
022        private Class<?> defaultValue;
023        private final SortedSet<String> legalValues;
024        private final Map<String,String> legalValueDesc;
025        private final Map<String,Class<?>> legalValueClass;
026        private final Map<Class<?>, String> classLegalValues;
027        
028        /**
029         * Creates a class type option description
030         * 
031         * @param group a reference to the option group.
032         * @param name  the name of the option.
033         * @param shortDescription      a short description of the option.
034         * @param flag  a short string that can be used in the command line.
035         * @param usage a string that explains the usage of the option.
036         * @throws OptionException
037         */
038        public ClassOption(OptionGroup group, 
039                                                String name, 
040                                                String shortDescription, 
041                                                String flag, 
042                                                String usage) throws MaltChainedException {
043                super(group, name, shortDescription, flag, usage);
044                legalValues = Collections.synchronizedSortedSet(new TreeSet<String>());
045                legalValueDesc = Collections.synchronizedMap(new HashMap<String,String>());
046                legalValueClass = Collections.synchronizedMap(new HashMap<String,Class<?>>());
047                classLegalValues = Collections.synchronizedMap(new HashMap<Class<?>, String>());
048        }
049
050        /* (non-Javadoc)
051         * @see org.maltparser.core.options.option.Option#getValueObject(java.lang.String)
052         */
053        public Object getValueObject(String value) throws MaltChainedException {
054                if (value == null) {
055                        return null;
056                } else if (legalValues.contains(value)) {
057                        return legalValueClass.get(value);
058                } else {
059                        throw new OptionException("'"+value+"' is not a legal value for the '"+getName()+"' option. ");
060                }       
061        }
062        
063        /* (non-Javadoc)
064         * @see org.maltparser.core.options.option.Option#getDefaultValueObject()
065         */
066        public Object getDefaultValueObject() throws OptionException {
067                return defaultValue;
068        }
069
070        /**
071         * Returns a string representation of particular class
072         * 
073         * @param clazz an class object
074         * @return      a string representation of particular class, if not present null is returned.
075         * @throws MaltChainedException
076         */
077        public String getLegalValueString(Class<?> clazz) throws MaltChainedException {
078                return classLegalValues.get(clazz);
079        }
080        
081        /* (non-Javadoc)
082         * @see org.maltparser.core.options.option.Option#setDefaultValue(java.lang.String)
083         */
084        public void setDefaultValue(String defaultValue) throws MaltChainedException {
085                if (defaultValue == null) {
086                        if (legalValues.isEmpty()) {
087                                throw new OptionException("The default value is null and the legal value set is empty for the '"+getName()+"' option. ");
088                        } else {
089                                this.defaultValue = legalValueClass.get(((TreeSet<String>)legalValueClass.keySet()).first()); 
090                        }
091                } else if (legalValues.contains(defaultValue.toLowerCase())) {
092                        this.defaultValue = legalValueClass.get(defaultValue.toLowerCase());
093                } else {
094                        throw new OptionException("The default value '"+defaultValue+"' is not a legal value for the '"+getName()+"' option. ");
095                }
096        }
097        
098        /**
099         * Returns the class that corresponds to the enumerate string value.
100         * 
101         * @param value an enumerate string value
102         * @return the class that corresponds to the enumerate string value.
103         */
104        public Class<?> getClazz(String value) {
105                return legalValueClass.get(value);
106        }
107
108        /**
109         * Adds a legal value that corresponds to a class
110         * 
111         * @param value a legal value name
112         * @param desc  a short description of the legal value
113         * @param classname     the fully qualified name of the class
114         * @throws OptionException
115         */
116        public void addLegalValue(String value, String desc, String classname) throws MaltChainedException {
117                if (value == null || value.equals("")) {
118                        throw new OptionException("The legal value is missing for the '"+getName()+"' option. ");
119                } else if (legalValues.contains(value.toLowerCase())) {
120                        throw new OptionException("The legal value for the '"+getName()+"' option already exists. ");
121                } else {
122                        legalValues.add(value.toLowerCase());
123                        if (desc == null || desc.equals("")) {
124                                legalValueDesc.put(value.toLowerCase(), "Description is missing. ");
125                        } else {
126                                legalValueDesc.put(value.toLowerCase(), desc);
127                        }
128                        if (classname == null || classname.equals("")) {
129                                throw new OptionException("The class name used by the '"+getName()+"' option is missing. ");
130                        } else {
131                                try {
132                                        Class<?> clazz = null;
133                                        if (PluginLoader.instance() != null) {
134                                                clazz = PluginLoader.instance().getClass(classname);
135                                        }
136                                        if (clazz == null) {
137                                                clazz = Class.forName(classname);
138                                        }
139                                        legalValueClass.put(value, clazz);
140                                        classLegalValues.put(clazz, value);
141                                } catch (ClassNotFoundException e) {
142                                        throw new OptionException("The class "+classname+" for the '"+getName()+"' option could not be found. ", e);
143                                }
144                        }
145                }
146        }
147        
148        /* (non-Javadoc)
149         * @see org.maltparser.core.options.option.Option#getDefaultValueString()
150         */
151        public String getDefaultValueString() {
152                return classLegalValues.get(defaultValue);
153        }
154        
155        /* (non-Javadoc)
156         * @see org.maltparser.core.options.option.Option#getStringRepresentation(java.lang.Object)
157         */
158        public String getStringRepresentation(Object value) {
159                if (value instanceof Class && classLegalValues.containsKey(value)) {
160                        return classLegalValues.get(value);
161                }
162                return null;
163        }
164        
165        /* (non-Javadoc)
166         * @see org.maltparser.core.options.option.Option#toString()
167         */
168        public String toString() {
169                final StringBuilder sb = new StringBuilder();
170                sb.append(super.toString());
171                Formatter formatter = new Formatter(sb);
172                for (String value : legalValues) {
173                        formatter.format("%2s%-10s - %-20s\n", "", value, legalValueDesc.get(value));
174                }
175                sb.append("-----------------------------------------------------------------------------\n");
176                return sb.toString();
177        }
178}