001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.cli2.option;
018    
019    import java.util.Iterator;
020    import java.util.ListIterator;
021    import java.util.Set;
022    
023    import org.apache.commons.cli2.DisplaySetting;
024    import org.apache.commons.cli2.Option;
025    import org.apache.commons.cli2.WriteableCommandLine;
026    import org.apache.commons.cli2.resource.ResourceConstants;
027    import org.apache.commons.cli2.resource.ResourceHelper;
028    
029    /**
030     * A base implementation of Option providing limited ground work for further
031     * Option implementations.
032     */
033    public abstract class OptionImpl implements Option {
034        private final int id;
035        private final boolean required;
036        private Option parent;
037    
038        /**
039         * Creates an OptionImpl with the specified id
040         * @param id the unique id of this Option
041         * @param required true iff this Option must be present
042         */
043        public OptionImpl(final int id,
044                          final boolean required) {
045            this.id = id;
046            this.required = required;
047        }
048    
049        public boolean canProcess(final WriteableCommandLine commandLine,
050                                  final ListIterator arguments) {
051            if (arguments.hasNext()) {
052                final String argument = (String) arguments.next();
053                arguments.previous();
054    
055                return canProcess(commandLine, argument);
056            } else {
057                return false;
058            }
059        }
060    
061        public String toString() {
062            final StringBuffer buffer = new StringBuffer();
063            appendUsage(buffer, DisplaySetting.ALL, null);
064    
065            return buffer.toString();
066        }
067    
068        public int getId() {
069            return id;
070        }
071    
072        public boolean equals(final Object thatObj) {
073            if (thatObj instanceof OptionImpl) {
074                final OptionImpl that = (OptionImpl) thatObj;
075    
076                return (getId() == that.getId()) &&
077                       equals(getPreferredName(), that.getPreferredName()) &&
078                       equals(getDescription(), that.getDescription()) &&
079                       equals(getPrefixes(), that.getPrefixes()) &&
080                       equals(getTriggers(), that.getTriggers());
081            } else {
082                return false;
083            }
084        }
085    
086        private boolean equals(Object left,
087                               Object right) {
088            if ((left == null) && (right == null)) {
089                return true;
090            } else if ((left == null) || (right == null)) {
091                return false;
092            } else {
093                return left.equals(right);
094            }
095        }
096    
097        public int hashCode() {
098            int hashCode = getId();
099            if (getPreferredName() != null) {
100                hashCode = (hashCode * 37) + getPreferredName().hashCode();
101            }
102    
103            if (getDescription() != null) {
104                hashCode = (hashCode * 37) + getDescription().hashCode();
105            }
106    
107            hashCode = (hashCode * 37) + getPrefixes().hashCode();
108            hashCode = (hashCode * 37) + getTriggers().hashCode();
109    
110            return hashCode;
111        }
112    
113        public Option findOption(String trigger) {
114            if (getTriggers().contains(trigger)) {
115                return this;
116            } else {
117                return null;
118            }
119        }
120    
121        public boolean isRequired() {
122            return required;
123        }
124    
125        public void defaults(final WriteableCommandLine commandLine) {
126            // nothing to do normally
127        }
128    
129        public Option getParent() {
130            return parent;
131        }
132    
133        public void setParent(Option parent) {
134            this.parent = parent;
135        }
136    
137        protected void checkPrefixes(final Set prefixes) {
138            // nothing to do if empty prefix list
139            if (prefixes.isEmpty()) {
140                return;
141            }
142    
143            // check preferred name
144            checkPrefix(prefixes, getPreferredName());
145    
146            // check triggers
147            this.getTriggers();
148    
149            for (final Iterator i = getTriggers().iterator(); i.hasNext();) {
150                checkPrefix(prefixes, (String) i.next());
151            }
152        }
153    
154        private void checkPrefix(final Set prefixes,
155                                 final String trigger) {
156            for (final Iterator i = prefixes.iterator(); i.hasNext();) {
157                String prefix = (String) i.next();
158    
159                if (trigger.startsWith(prefix)) {
160                    return;
161                }
162            }
163    
164            final ResourceHelper helper = ResourceHelper.getResourceHelper();
165            final String message =
166                helper.getMessage(ResourceConstants.OPTION_TRIGGER_NEEDS_PREFIX, trigger,
167                                  prefixes.toString());
168            throw new IllegalArgumentException(message);
169        }
170    }