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.builder; 018 019import java.util.Iterator; 020import java.util.LinkedHashSet; 021import java.util.Set; 022 023import org.apache.commons.cli2.Argument; 024import org.apache.commons.cli2.Option; 025import org.apache.commons.cli2.validation.ClassValidator; 026import org.apache.commons.cli2.validation.DateValidator; 027import org.apache.commons.cli2.validation.FileValidator; 028import org.apache.commons.cli2.validation.NumberValidator; 029import org.apache.commons.cli2.validation.UrlValidator; 030import org.apache.commons.cli2.validation.Validator; 031 032/** 033 * Builds Options using a String pattern 034 */ 035//TODO Document and link to the acceptable patterns 036public class PatternBuilder { 037 038 private final GroupBuilder gbuilder; 039 private final DefaultOptionBuilder obuilder; 040 private final ArgumentBuilder abuilder; 041 042 /** 043 * Creates a new PatternBuilder 044 */ 045 public PatternBuilder() { 046 this( 047 new GroupBuilder(), 048 new DefaultOptionBuilder(), 049 new ArgumentBuilder()); 050 } 051 052 /** 053 * Creates a new PatternBuilder 054 * @param gbuilder the GroupBuilder to use 055 * @param obuilder the DefaultOptionBuilder to use 056 * @param abuilder the ArgumentBuilder to use 057 */ 058 public PatternBuilder( 059 final GroupBuilder gbuilder, 060 final DefaultOptionBuilder obuilder, 061 final ArgumentBuilder abuilder) { 062 this.gbuilder = gbuilder; 063 this.obuilder = obuilder; 064 this.abuilder = abuilder; 065 } 066 067 private final Set options = new LinkedHashSet(); 068 069 /** 070 * Creates a new Option instance. 071 * @return a new Option instance 072 */ 073 public Option create() { 074 final Option option; 075 076 if (options.size() == 1) { 077 option = (Option)options.iterator().next(); 078 } 079 else { 080 gbuilder.reset(); 081 for (final Iterator i = options.iterator(); i.hasNext();) { 082 gbuilder.withOption((Option)i.next()); 083 } 084 option = gbuilder.create(); 085 } 086 087 reset(); 088 089 return option; 090 } 091 092 /** 093 * Resets this builder. 094 * @return this builder 095 */ 096 public PatternBuilder reset() { 097 options.clear(); 098 return this; 099 } 100 101 private void createOption( 102 final char type, 103 final boolean required, 104 final char opt) { 105 final Argument argument; 106 if (type != ' ') { 107 abuilder.reset(); 108 abuilder.withValidator(validator(type)); 109 if (required) { 110 abuilder.withMinimum(1); 111 } 112 if (type != '*') { 113 abuilder.withMaximum(1); 114 } 115 argument = abuilder.create(); 116 } 117 else { 118 argument = null; 119 } 120 121 obuilder.reset(); 122 obuilder.withArgument(argument); 123 obuilder.withShortName(String.valueOf(opt)); 124 obuilder.withRequired(required); 125 126 options.add(obuilder.create()); 127 } 128 129 /** 130 * Builds an Option using a pattern string. 131 * @param pattern the pattern to build from 132 */ 133 public void withPattern(final String pattern) { 134 int sz = pattern.length(); 135 136 char opt = ' '; 137 char ch = ' '; 138 char type = ' '; 139 boolean required = false; 140 141 for (int i = 0; i < sz; i++) { 142 ch = pattern.charAt(i); 143 144 switch (ch) { 145 case '!' : 146 required = true; 147 break; 148 case '@' : 149 case ':' : 150 case '%' : 151 case '+' : 152 case '#' : 153 case '<' : 154 case '>' : 155 case '*' : 156 case '/' : 157 type = ch; 158 break; 159 default : 160 if (opt != ' ') { 161 createOption(type, required, opt); 162 required = false; 163 type = ' '; 164 } 165 166 opt = ch; 167 } 168 } 169 170 if (opt != ' ') { 171 createOption(type, required, opt); 172 } 173 } 174 175 private static Validator validator(final char c) { 176 switch (c) { 177 case '@' : 178 final ClassValidator classv = new ClassValidator(); 179 classv.setInstance(true); 180 return classv; 181 case '+' : 182 final ClassValidator instancev = new ClassValidator(); 183 return instancev; 184 //case ':':// no validator needed for a string 185 case '%' : 186 return NumberValidator.getNumberInstance(); 187 case '#' : 188 return DateValidator.getDateInstance(); 189 case '<' : 190 final FileValidator existingv = new FileValidator(); 191 existingv.setExisting(true); 192 existingv.setFile(true); 193 return existingv; 194 case '>' : 195 case '*' : 196 return new FileValidator(); 197 case '/' : 198 return new UrlValidator(); 199 default : 200 return null; 201 } 202 } 203}