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 */ 017package org.apache.commons.cli2.option; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.Comparator; 022import java.util.List; 023import java.util.ListIterator; 024import java.util.Set; 025 026import org.apache.commons.cli2.Argument; 027import org.apache.commons.cli2.DisplaySetting; 028import org.apache.commons.cli2.Group; 029import org.apache.commons.cli2.Option; 030import org.apache.commons.cli2.OptionException; 031import org.apache.commons.cli2.Parent; 032import org.apache.commons.cli2.WriteableCommandLine; 033 034/** 035 * A base implementation of Parent providing limited ground work for further 036 * Parent implementations. 037 */ 038public abstract class ParentImpl 039 extends OptionImpl implements Parent { 040 private static final char NUL = '\0'; 041 private final Group children; 042 private final Argument argument; 043 private final String description; 044 045 protected ParentImpl(final Argument argument, 046 final Group children, 047 final String description, 048 final int id, 049 final boolean required) { 050 super(id, required); 051 this.children = children; 052 this.argument = argument; 053 this.description = description; 054 } 055 056 /* 057 * (non-Javadoc) 058 * 059 * @see org.apache.commons.cli2.Option#process(org.apache.commons.cli2.CommandLine, 060 * java.util.ListIterator) 061 */ 062 public void process(final WriteableCommandLine commandLine, 063 final ListIterator arguments) 064 throws OptionException { 065 if (argument != null) { 066 handleInitialSeparator(arguments, argument.getInitialSeparator()); 067 } 068 069 processParent(commandLine, arguments); 070 071 if (argument != null) { 072 argument.processValues(commandLine, arguments, this); 073 } 074 075 if ((children != null) && children.canProcess(commandLine, arguments)) { 076 children.process(commandLine, arguments); 077 } 078 } 079 080 /* 081 * (non-Javadoc) 082 * 083 * @see org.apache.commons.cli2.Option#canProcess(java.lang.String) 084 */ 085 public boolean canProcess(final WriteableCommandLine commandLine, 086 final String arg) { 087 final Set triggers = getTriggers(); 088 089 if (argument != null) { 090 final char separator = argument.getInitialSeparator(); 091 092 // if there is a valid separator character 093 if (separator != NUL) { 094 final int initialIndex = arg.indexOf(separator); 095 096 // if there is a separator present 097 if (initialIndex > 0) { 098 return triggers.contains(arg.substring(0, initialIndex)); 099 } 100 } 101 } 102 103 return triggers.contains(arg); 104 } 105 106 /* 107 * (non-Javadoc) 108 * 109 * @see org.apache.commons.cli2.Option#prefixes() 110 */ 111 public Set getPrefixes() { 112 return (children == null) ? Collections.EMPTY_SET : children.getPrefixes(); 113 } 114 115 /* 116 * (non-Javadoc) 117 * 118 * @see org.apache.commons.cli2.Option#validate(org.apache.commons.cli2.CommandLine) 119 */ 120 public void validate(WriteableCommandLine commandLine) 121 throws OptionException { 122 if (commandLine.hasOption(this)) { 123 if (argument != null) { 124 argument.validate(commandLine, this); 125 } 126 127 if (children != null) { 128 children.validate(commandLine); 129 } 130 } 131 } 132 133 /* 134 * (non-Javadoc) 135 * 136 * @see org.apache.commons.cli2.Option#appendUsage(java.lang.StringBuffer, 137 * java.util.Set, java.util.Comparator) 138 */ 139 public void appendUsage(final StringBuffer buffer, 140 final Set helpSettings, 141 final Comparator comp) { 142 final boolean displayArgument = 143 (this.argument != null) && 144 helpSettings.contains(DisplaySetting.DISPLAY_PARENT_ARGUMENT); 145 final boolean displayChildren = 146 (this.children != null) && 147 helpSettings.contains(DisplaySetting.DISPLAY_PARENT_CHILDREN); 148 149 if (displayArgument) { 150 buffer.append(' '); 151 argument.appendUsage(buffer, helpSettings, comp); 152 } 153 154 if (displayChildren) { 155 buffer.append(' '); 156 children.appendUsage(buffer, helpSettings, comp); 157 } 158 } 159 160 /** 161 * @return a description of this parent option 162 */ 163 public String getDescription() { 164 return description; 165 } 166 167 /* 168 * (non-Javadoc) 169 * 170 * @see org.apache.commons.cli2.Option#helpLines(int, java.util.Set, 171 * java.util.Comparator) 172 */ 173 public List helpLines(final int depth, 174 final Set helpSettings, 175 final Comparator comp) { 176 final List helpLines = new ArrayList(); 177 helpLines.add(new HelpLineImpl(this, depth)); 178 179 if (helpSettings.contains(DisplaySetting.DISPLAY_PARENT_ARGUMENT) && (argument != null)) { 180 helpLines.addAll(argument.helpLines(depth + 1, helpSettings, comp)); 181 } 182 183 if (helpSettings.contains(DisplaySetting.DISPLAY_PARENT_CHILDREN) && (children != null)) { 184 helpLines.addAll(children.helpLines(depth + 1, helpSettings, comp)); 185 } 186 187 return helpLines; 188 } 189 190 /** 191 * @return Returns the argument. 192 */ 193 public Argument getArgument() { 194 return argument; 195 } 196 197 /** 198 * @return Returns the children. 199 */ 200 public Group getChildren() { 201 return children; 202 } 203 204 /** 205 * Split the token using the specified separator character. 206 * @param arguments the current position in the arguments iterator 207 * @param separator the separator char to split on 208 */ 209 private void handleInitialSeparator(final ListIterator arguments, 210 final char separator) { 211 // next token 212 final String newArgument = (String) arguments.next(); 213 214 // split the token 215 final int initialIndex = newArgument.indexOf(separator); 216 217 if (initialIndex > 0) { 218 arguments.remove(); 219 arguments.add(newArgument.substring(0, initialIndex)); 220 String value = newArgument.substring(initialIndex + 1); 221 // The value obviously isn't an option, so we need to quote it if looks like an option. 222 // The quotes will be removed later 223 if (value.startsWith("-")) { 224 value = '"' + value + '"'; 225 } 226 arguments.add(value); 227 arguments.previous(); 228 } 229 230 arguments.previous(); 231 } 232 233 /* 234 * @see org.apache.commons.cli2.Option#findOption(java.lang.String) 235 */ 236 public Option findOption(final String trigger) { 237 final Option found = super.findOption(trigger); 238 239 if ((found == null) && (children != null)) { 240 return children.findOption(trigger); 241 } else { 242 return found; 243 } 244 } 245 246 public void defaults(final WriteableCommandLine commandLine) { 247 super.defaults(commandLine); 248 249 if (argument != null) { 250 argument.defaultValues(commandLine, this); 251 } 252 253 if (children != null) { 254 children.defaults(commandLine); 255 } 256 } 257}