private Set<String> getLocalPlayersAsUuidStrings() { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); for (ProxiedPlayer player : getProxy().getPlayers()) { builder.add(player.getUniqueId().toString()); } return builder.build(); }
final Set<UUID> getPlayers() { ImmutableSet.Builder<UUID> setBuilder = ImmutableSet.builder(); if (pool != null) { try (Jedis rsc = pool.getResource()) { List<String> keys = new ArrayList<>(); for (String i : getServerIds()) { keys.add("proxy:" + i + ":usersOnline"); } if (!keys.isEmpty()) { Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()])); if (users != null && !users.isEmpty()) { for (String user : users) { try { setBuilder = setBuilder.add(UUID.fromString(user)); } catch (IllegalArgumentException ignored) { } } } } } catch (JedisConnectionException e) { // Redis server has disappeared! getLogger() .log( Level.SEVERE, "Unable to get connection from pool - did your Redis server go away?", e); throw new RuntimeException("Unable to get all players online", e); } } return setBuilder.build(); }
public static boolean ignoredSchemaRow(Row row) { try { return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.key)); } catch (CharacterCodingException e) { throw new RuntimeException(e); } }
/** * Endpoints which are migrating to the new tokens * * @return set of addresses of moving endpoints */ public Set<Pair<Token, InetAddress>> getMovingEndpoints() { lock.readLock().lock(); try { return ImmutableSet.copyOf(movingEndpoints); } finally { lock.readLock().unlock(); } }
/** caller should not modify leavingEndpoints */ public Set<InetAddress> getLeavingEndpoints() { lock.readLock().lock(); try { return ImmutableSet.copyOf(leavingEndpoints); } finally { lock.readLock().unlock(); } }
public Set<InetAddress> getAllEndpoints() { lock.readLock().lock(); try { return ImmutableSet.copyOf(endpointToHostIdMap.keySet()); } finally { lock.readLock().unlock(); } }
public Set<UUID> getPlayersOnProxy(String server) { checkArgument(getServerIds().contains(server), server + " is not a valid proxy ID"); try (Jedis jedis = pool.getResource()) { Set<String> users = jedis.smembers("proxy:" + server + ":usersOnline"); ImmutableSet.Builder<UUID> builder = ImmutableSet.builder(); for (String user : users) { builder.add(UUID.fromString(user)); } return builder.build(); } }
final Set<UUID> getPlayersOnServer(@NonNull String server) { checkArgument(getProxy().getServers().containsKey(server), "server does not exist"); Collection<String> asStrings = (Collection<String>) getServerPlayersScript.eval( ImmutableList.<String>of(), ImmutableList.<String>of(server)); ImmutableSet.Builder<UUID> builder = ImmutableSet.builder(); for (String s : asStrings) { builder.add(UUID.fromString(s)); } return builder.build(); }
private Set<TestBean> buildBeans() { ImmutableSet.Builder<TestBean> aBuilder = ImmutableSet.builder(); aBuilder.add( new TestBean("John", "Doe", "blue"), new TestBean("Sally", "Smith", "red"), new TestBean("Abe", "Lincoln", "black"), new TestBean("Albus", "Dumbledore", "purple"), new TestBean("Herminoe", "Grainger", "pink")); return aBuilder.build(); }
private void writeDelegateMethods( final ClassVisitor visitor, final Type generatedType, StructSchema<?> delegateSchema, Set<Class<?>> typesToDelegate) { Class<?> delegateClass = delegateSchema.getType().getConcreteClass(); Type delegateType = Type.getType(delegateClass); Map<Equivalence.Wrapper<Method>, Map<Class<?>, Method>> methodsToDelegate = Maps.newHashMap(); for (Class<?> typeToDelegate : typesToDelegate) { for (Method methodToDelegate : typeToDelegate.getMethods()) { if (ModelSchemaUtils.isIgnoredMethod(methodToDelegate)) { continue; } Equivalence.Wrapper<Method> methodKey = METHOD_EQUIVALENCE.wrap(methodToDelegate); Map<Class<?>, Method> methodsByReturnType = methodsToDelegate.get(methodKey); if (methodsByReturnType == null) { methodsByReturnType = Maps.newHashMap(); methodsToDelegate.put(methodKey, methodsByReturnType); } methodsByReturnType.put(methodToDelegate.getReturnType(), methodToDelegate); } } Set<Equivalence.Wrapper<Method>> delegateMethodKeys = ImmutableSet.copyOf( Iterables.transform( Arrays.asList(delegateClass.getMethods()), new Function<Method, Equivalence.Wrapper<Method>>() { @Override public Equivalence.Wrapper<Method> apply(Method method) { return METHOD_EQUIVALENCE.wrap(method); } })); for (Map.Entry<Equivalence.Wrapper<Method>, Map<Class<?>, Method>> entry : methodsToDelegate.entrySet()) { Equivalence.Wrapper<Method> methodKey = entry.getKey(); if (!delegateMethodKeys.contains(methodKey)) { continue; } Map<Class<?>, Method> methodsByReturnType = entry.getValue(); for (Method methodToDelegate : methodsByReturnType.values()) { writeDelegatedMethod(visitor, generatedType, delegateType, methodToDelegate); } } }
public DocIndexMetaData(IndexMetaData metaData, TableIdent ident) throws IOException { this.ident = ident; this.metaData = metaData; this.isAlias = !metaData.getIndex().equals(ident.esName()); this.numberOfShards = metaData.numberOfShards(); final Settings settings = metaData.getSettings(); this.numberOfReplicas = NumberOfReplicas.fromSettings(settings); this.aliases = ImmutableSet.copyOf(metaData.aliases().keys().toArray(String.class)); this.defaultMappingMetaData = this.metaData.mappingOrDefault(Constants.DEFAULT_MAPPING_TYPE); if (defaultMappingMetaData == null) { this.defaultMappingMap = new HashMap<>(); } else { this.defaultMappingMap = this.defaultMappingMetaData.sourceAsMap(); } this.tableParameters = TableParameterInfo.tableParametersFromIndexMetaData(metaData); prepareCrateMeta(); }
/** * Returns all the fields that match the given pattern. If the pattern is prefixed with a type * then the fields will be returned with a type prefix. */ public Set<String> simpleMatchToIndexNames(String pattern) { if (!Regex.isSimpleMatchPattern(pattern)) { return ImmutableSet.of(pattern); } int dotIndex = pattern.indexOf('.'); if (dotIndex != -1) { String possibleType = pattern.substring(0, dotIndex); DocumentMapper possibleDocMapper = mappers.get(possibleType); if (possibleDocMapper != null) { Set<String> typedFields = Sets.newHashSet(); for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) { typedFields.add(possibleType + "." + indexName); } return typedFields; } } return fieldMappers.simpleMatchToIndexNames(pattern); }
/** * Returns all the fields that match the given pattern, with an optional narrowing based on a list * of types. */ public Set<String> simpleMatchToIndexNames(String pattern, @Nullable String[] types) { if (types == null || types.length == 0) { return simpleMatchToIndexNames(pattern); } if (types.length == 1 && types[0].equals("_all")) { return simpleMatchToIndexNames(pattern); } if (!Regex.isSimpleMatchPattern(pattern)) { return ImmutableSet.of(pattern); } Set<String> fields = Sets.newHashSet(); for (String type : types) { DocumentMapper possibleDocMapper = mappers.get(type); if (possibleDocMapper != null) { for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) { fields.add(indexName); } } } return fields; }
public Set<String> getSubSchemaNames() { return ImmutableSet.of(); }
public class Schema { private static final Logger logger = LoggerFactory.getLogger(Schema.class); public static final Schema instance = new Schema(); /** * longest permissible KS or CF name. Our main concern is that filename not be more than 255 * characters; the filename will contain both the KS and CF names. Since non-schema-name * components only take up ~64 characters, we could allow longer names than this, but on Windows, * the entire path should be not greater than 255 characters, so a lower limit here helps avoid * problems. See CASSANDRA-4110. */ public static final int NAME_LENGTH = 48; /* metadata map for faster table lookup */ private final Map<String, KSMetaData> tables = new NonBlockingHashMap<String, KSMetaData>(); /* Table objects, one per keyspace. Only one instance should ever exist for any given keyspace. */ private final Map<String, Table> tableInstances = new NonBlockingHashMap<String, Table>(); /* metadata map for faster ColumnFamily lookup */ private final BiMap<Pair<String, String>, UUID> cfIdMap = HashBiMap.create(); // mapping from old ColumnFamily Id (Integer) to a new version which is UUID private final BiMap<Integer, UUID> oldCfIdMap = HashBiMap.create(); private volatile UUID version; // 59adb24e-f3cd-3e02-97f0-5b395827453f public static final UUID emptyVersion; public static final ImmutableSet<String> systemKeyspaceNames = ImmutableSet.of(Table.SYSTEM_KS, Tracing.TRACE_KS); static { try { emptyVersion = UUID.nameUUIDFromBytes(MessageDigest.getInstance("MD5").digest()); } catch (NoSuchAlgorithmException e) { throw new AssertionError(); } } /** Initialize empty schema object */ public Schema() {} /** * Load up non-system tables * * @param tableDefs The non-system table definitions * @return self to support chaining calls */ public Schema load(Collection<KSMetaData> tableDefs) { for (KSMetaData def : tableDefs) load(def); return this; } /** * Load specific keyspace into Schema * * @param keyspaceDef The keyspace to load up * @return self to support chaining calls */ public Schema load(KSMetaData keyspaceDef) { for (CFMetaData cfm : keyspaceDef.cfMetaData().values()) load(cfm); setTableDefinition(keyspaceDef); return this; } /** * Get table instance by name * * @param tableName The name of the table * @return Table object or null if table was not found */ public Table getTableInstance(String tableName) { return tableInstances.get(tableName); } /** * Store given Table instance to the schema * * @param table The Table instance to store * @throws IllegalArgumentException if Table is already stored */ public void storeTableInstance(Table table) { if (tableInstances.containsKey(table.name)) throw new IllegalArgumentException( String.format("Table %s was already initialized.", table.name)); tableInstances.put(table.name, table); } /** * Remove table from schema * * @param tableName The name of the table to remove * @return removed table instance or null if it wasn't found */ public Table removeTableInstance(String tableName) { return tableInstances.remove(tableName); } /** * Remove table definition from system * * @param ksm The table definition to remove */ public void clearTableDefinition(KSMetaData ksm) { tables.remove(ksm.name); } /** * Given a table name & column family name, get the column family meta data. If the table name or * column family name is not valid this function returns null. * * @param tableName The table name * @param cfName The ColumnFamily name * @return ColumnFamily Metadata object or null if it wasn't found */ public CFMetaData getCFMetaData(String tableName, String cfName) { assert tableName != null; KSMetaData ksm = tables.get(tableName); return (ksm == null) ? null : ksm.cfMetaData().get(cfName); } /** * Get ColumnFamily metadata by its identifier * * @param cfId The ColumnFamily identifier * @return metadata about ColumnFamily */ public CFMetaData getCFMetaData(UUID cfId) { Pair<String, String> cf = getCF(cfId); return (cf == null) ? null : getCFMetaData(cf.left, cf.right); } public CFMetaData getCFMetaData(Descriptor descriptor) { return getCFMetaData(descriptor.ksname, descriptor.cfname); } /** * Get type of the ColumnFamily but it's keyspace/name * * @param ksName The keyspace name * @param cfName The ColumnFamily name * @return The type of the ColumnFamily */ public ColumnFamilyType getColumnFamilyType(String ksName, String cfName) { assert ksName != null && cfName != null; CFMetaData cfMetaData = getCFMetaData(ksName, cfName); return (cfMetaData == null) ? null : cfMetaData.cfType; } /** * Get column comparator for ColumnFamily but it's keyspace/name * * @param ksName The keyspace name * @param cfName The ColumnFamily name * @return The comparator of the ColumnFamily */ public AbstractType<?> getComparator(String ksName, String cfName) { assert ksName != null; CFMetaData cfmd = getCFMetaData(ksName, cfName); if (cfmd == null) throw new IllegalArgumentException( "Unknown ColumnFamily " + cfName + " in keyspace " + ksName); return cfmd.comparator; } /** * Get subComparator of the ColumnFamily * * @param ksName The keyspace name * @param cfName The ColumnFamily name * @return The subComparator of the ColumnFamily */ public AbstractType<?> getSubComparator(String ksName, String cfName) { assert ksName != null; return getCFMetaData(ksName, cfName).subcolumnComparator; } /** * Get value validator for specific column * * @param ksName The keyspace name * @param cfName The ColumnFamily name * @param column The name of the column * @return value validator specific to the column or default (per-cf) one */ public AbstractType<?> getValueValidator(String ksName, String cfName, ByteBuffer column) { return getCFMetaData(ksName, cfName).getValueValidator(column); } /** * Get metadata about table by its name * * @param table The name of the table * @return The table metadata or null if it wasn't found */ public KSMetaData getKSMetaData(String table) { assert table != null; return tables.get(table); } /** @return collection of the non-system tables */ public List<String> getNonSystemTables() { return ImmutableList.copyOf(Sets.difference(tables.keySet(), systemKeyspaceNames)); } /** * Get metadata about table by its name * * @param table The name of the table * @return The table metadata or null if it wasn't found */ public KSMetaData getTableDefinition(String table) { return getKSMetaData(table); } /** * Get metadata about table inner ColumnFamilies * * @param tableName The name of the table * @return metadata about ColumnFamilies the belong to the given table */ public Map<String, CFMetaData> getTableMetaData(String tableName) { assert tableName != null; KSMetaData ksm = tables.get(tableName); assert ksm != null; return ksm.cfMetaData(); } /** @return collection of the all table names registered in the system (system and non-system) */ public Set<String> getTables() { return tables.keySet(); } /** * @return collection of the metadata about all tables registered in the system (system and * non-system) */ public Collection<KSMetaData> getTableDefinitions() { return tables.values(); } /** * Update (or insert) new table definition * * @param ksm The metadata about table */ public void setTableDefinition(KSMetaData ksm) { assert ksm != null; tables.put(ksm.name, ksm); } /* ColumnFamily query/control methods */ public void addOldCfIdMapping(Integer oldId, UUID newId) { if (oldId == null) return; oldCfIdMap.put(oldId, newId); } public UUID convertOldCfId(Integer oldCfId) throws UnknownColumnFamilyException { UUID cfId = oldCfIdMap.get(oldCfId); if (cfId == null) throw new UnknownColumnFamilyException( "ColumnFamily identified by old " + oldCfId + " was not found.", null); return cfId; } public Integer convertNewCfId(UUID newCfId) { return oldCfIdMap.containsValue(newCfId) ? oldCfIdMap.inverse().get(newCfId) : null; } /** * @param cfId The identifier of the ColumnFamily to lookup * @return The (ksname,cfname) pair for the given id, or null if it has been dropped. */ public Pair<String, String> getCF(UUID cfId) { return cfIdMap.inverse().get(cfId); } /** * Lookup keyspace/ColumnFamily identifier * * @param ksName The keyspace name * @param cfName The ColumnFamily name * @return The id for the given (ksname,cfname) pair, or null if it has been dropped. */ public UUID getId(String ksName, String cfName) { return cfIdMap.get(Pair.create(ksName, cfName)); } /** * Load individual ColumnFamily Definition to the schema (to make ColumnFamily lookup faster) * * @param cfm The ColumnFamily definition to load */ public void load(CFMetaData cfm) { Pair<String, String> key = Pair.create(cfm.ksName, cfm.cfName); if (cfIdMap.containsKey(key)) throw new RuntimeException( String.format( "Attempting to load already loaded column family %s.%s", cfm.ksName, cfm.cfName)); logger.debug("Adding {} to cfIdMap", cfm); cfIdMap.put(key, cfm.cfId); } /** * Used for ColumnFamily data eviction out from the schema * * @param cfm The ColumnFamily Definition to evict */ public void purge(CFMetaData cfm) { cfIdMap.remove(Pair.create(cfm.ksName, cfm.cfName)); } /* Version control */ /** @return current schema version */ public UUID getVersion() { return version; } /** * Read schema from system table and calculate MD5 digest of every row, resulting digest will be * converted into UUID which would act as content-based version of the schema. */ public void updateVersion() { try { MessageDigest versionDigest = MessageDigest.getInstance("MD5"); for (Row row : SystemTable.serializedSchema()) { if (invalidSchemaRow(row) || ignoredSchemaRow(row)) continue; row.cf.updateDigest(versionDigest); } version = UUID.nameUUIDFromBytes(versionDigest.digest()); SystemTable.updateSchemaVersion(version); } catch (Exception e) { throw new RuntimeException(e); } } /* * Like updateVersion, but also announces via gossip */ public void updateVersionAndAnnounce() { updateVersion(); MigrationManager.passiveAnnounce(version); } /** Clear all KS/CF metadata and reset version. */ public synchronized void clear() { for (String table : getNonSystemTables()) { KSMetaData ksm = getTableDefinition(table); for (CFMetaData cfm : ksm.cfMetaData().values()) purge(cfm); clearTableDefinition(ksm); } updateVersionAndAnnounce(); } public static boolean invalidSchemaRow(Row row) { return row.cf == null || (row.cf.isMarkedForDelete() && row.cf.isEmpty()); } public static boolean ignoredSchemaRow(Row row) { try { return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.key)); } catch (CharacterCodingException e) { throw new RuntimeException(e); } } }
/** * Generates an implementation of the given managed type. * * <p>The generated class will implement/extend the managed type and will: * * <ul> * <li>provide implementations for abstract getters and setters that delegate to model nodes * <li>provide a `toString()` implementation * <li>mix-in implementation of {@link ManagedInstance} * <li>provide a constructor that accepts a {@link ModelElementState}, which will be used to * implement the above. * </ul> * * In case a delegate schema is supplied, the generated class will also have: * * <ul> * <li>a constructor that also takes a delegate instance * <li>methods that call through to the delegate instance * </ul> */ public <T, M extends T, D extends T> Class<? extends M> generate( StructSchema<M> viewSchema, @Nullable StructSchema<D> delegateSchema) { if (delegateSchema != null && Modifier.isAbstract(delegateSchema.getType().getConcreteClass().getModifiers())) { throw new IllegalArgumentException("Delegate type must be null or a non-abstract type"); } ClassWriter visitor = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); ModelType<M> viewType = viewSchema.getType(); StringBuilder generatedTypeNameBuilder = new StringBuilder(viewType.getName()); if (delegateSchema != null) { generatedTypeNameBuilder .append("$BackedBy_") .append(delegateSchema.getType().getName().replaceAll("\\.", "_")); } else { generatedTypeNameBuilder.append("$Impl"); } String generatedTypeName = generatedTypeNameBuilder.toString(); Type generatedType = Type.getType("L" + generatedTypeName.replaceAll("\\.", "/") + ";"); Class<M> viewClass = viewType.getConcreteClass(); Class<?> superclass; final ImmutableSet.Builder<String> interfacesToImplement = ImmutableSet.builder(); final ImmutableSet.Builder<Class<?>> typesToDelegate = ImmutableSet.builder(); typesToDelegate.add(viewClass); interfacesToImplement.add(MANAGED_INSTANCE_TYPE); if (viewClass.isInterface()) { superclass = Object.class; interfacesToImplement.add(Type.getInternalName(viewClass)); } else { superclass = viewClass; } // TODO:LPTR This should be removed once BinaryContainer is a ModelMap // We need to also implement all the interfaces of the delegate type because otherwise // BinaryContainer won't recognize managed binaries as BinarySpecInternal if (delegateSchema != null) { ModelSchemaUtils.walkTypeHierarchy( delegateSchema.getType().getConcreteClass(), new ModelSchemaUtils.TypeVisitor<D>() { @Override public void visitType(Class<? super D> type) { if (type.isInterface()) { typesToDelegate.add(type); interfacesToImplement.add(Type.getInternalName(type)); } } }); } generateProxyClass( visitor, viewSchema, delegateSchema, interfacesToImplement.build(), typesToDelegate.build(), generatedType, Type.getType(superclass)); ClassLoader targetClassLoader = viewClass.getClassLoader(); if (delegateSchema != null) { // TODO - remove this once the above is removed try { viewClass.getClassLoader().loadClass(delegateSchema.getType().getConcreteClass().getName()); } catch (ClassNotFoundException e) { // Delegate class is not visible to managed view type -> view type is more general than // delegate type, so use the delegate classloader instead targetClassLoader = delegateSchema.getType().getConcreteClass().getClassLoader(); } } return defineClass(visitor, targetClassLoader, generatedTypeName); }
public static class Builder { private String[] arguments = new String[0]; private Set<Character> expectedValueFlags = ImmutableSet.of(); private boolean allowHangingFlag = false; private Namespace namespace = new Namespace(); public String[] getArguments() { return Arrays.copyOf(arguments, arguments.length); } public Builder setArguments(String[] arguments) { checkNotNull(arguments, "arguments"); String[] newArguments = new String[arguments.length + 1]; newArguments[0] = "_"; System.arraycopy(arguments, 0, newArguments, 1, arguments.length); this.arguments = newArguments; return this; } public Builder setArguments(String arguments) { checkNotNull(arguments, "arguments"); setArguments(split(arguments)); return this; } public Builder setCommandAndArguments(String[] arguments) { checkNotNull(arguments, "arguments"); this.arguments = Arrays.copyOf(arguments, arguments.length); return this; } public Builder setCommandAndArguments(String arguments) { checkNotNull(arguments, "arguments"); setCommandAndArguments(split(arguments)); return this; } public Set<Character> getExpectedValueFlags() { return expectedValueFlags; } public Builder setExpectedValueFlags(Set<Character> expectedValueFlags) { this.expectedValueFlags = ImmutableSet.copyOf(expectedValueFlags); return this; } public boolean isAllowHangingFlag() { return allowHangingFlag; } public Builder setAllowHangingFlag(boolean allowHangingFlag) { this.allowHangingFlag = allowHangingFlag; return this; } public Namespace getNamespace() { return namespace; } public Builder setNamespace(Namespace namespace) { checkNotNull(namespace, "namespace"); this.namespace = namespace; return this; } public CommandContext build() throws CommandException { return new CommandContext(arguments, expectedValueFlags, allowHangingFlag, namespace); } }
/** * Parse the given array of arguments. * * <p>Empty arguments are removed from the list of arguments. * * @param args an array with arguments * @param expectedValueFlags a set containing all value flags (pass null to disable value flag * parsing) * @param allowHangingFlag true if hanging flags are allowed * @param namespace the locals, null to create empty one * @throws CommandException thrown on a parsing error */ public CommandContext( String[] args, Set<Character> expectedValueFlags, boolean allowHangingFlag, Namespace namespace) throws CommandException { if (expectedValueFlags == null) { expectedValueFlags = Collections.emptySet(); } originalArgs = args; command = args[0]; this.namespace = namespace != null ? namespace : new Namespace(); boolean isHanging = false; SuggestionContext suggestionContext = SuggestionContext.hangingValue(); // Eliminate empty args and combine multiword args first List<Integer> argIndexList = new ArrayList<Integer>(args.length); List<String> argList = new ArrayList<String>(args.length); for (int i = 1; i < args.length; ++i) { isHanging = false; String arg = args[i]; if (arg.isEmpty()) { isHanging = true; continue; } argIndexList.add(i); switch (arg.charAt(0)) { case '\'': case '"': final StringBuilder build = new StringBuilder(); final char quotedChar = arg.charAt(0); int endIndex; for (endIndex = i; endIndex < args.length; ++endIndex) { final String arg2 = args[endIndex]; if (arg2.charAt(arg2.length() - 1) == quotedChar && arg2.length() > 1) { if (endIndex != i) build.append(' '); build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1)); break; } else if (endIndex == i) { build.append(arg2.substring(1)); } else { build.append(' ').append(arg2); } } if (endIndex < args.length) { arg = build.toString(); i = endIndex; } // In case there is an empty quoted string if (arg.isEmpty()) { continue; } // else raise exception about hanging quotes? } argList.add(arg); } // Then flags List<Integer> originalArgIndices = Lists.newArrayListWithCapacity(argIndexList.size()); List<String> parsedArgs = Lists.newArrayListWithCapacity(argList.size()); Map<Character, String> valueFlags = Maps.newHashMap(); List<Character> booleanFlags = Lists.newArrayList(); for (int nextArg = 0; nextArg < argList.size(); ) { // Fetch argument String arg = argList.get(nextArg++); suggestionContext = SuggestionContext.hangingValue(); // Not a flag? if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z\\?]+$")) { if (!isHanging) { suggestionContext = SuggestionContext.lastValue(); } originalArgIndices.add(argIndexList.get(nextArg - 1)); parsedArgs.add(arg); continue; } // Handle flag parsing terminator -- if (arg.equals("--")) { while (nextArg < argList.size()) { originalArgIndices.add(argIndexList.get(nextArg)); parsedArgs.add(argList.get(nextArg++)); } break; } // Go through the flag characters for (int i = 1; i < arg.length(); ++i) { char flagName = arg.charAt(i); if (expectedValueFlags.contains(flagName)) { if (valueFlags.containsKey(flagName)) { throw new CommandException("Value flag '" + flagName + "' already given"); } if (nextArg >= argList.size()) { if (allowHangingFlag) { suggestionContext = SuggestionContext.flag(flagName); break; } else { throw new CommandException("No value specified for the '-" + flagName + "' flag."); } } // If it is a value flag, read another argument and add it valueFlags.put(flagName, argList.get(nextArg++)); if (!isHanging) { suggestionContext = SuggestionContext.flag(flagName); } } else { booleanFlags.add(flagName); } } } ImmutableMap.Builder<Character, String> allFlagsBuilder = new ImmutableMap.Builder<Character, String>().putAll(valueFlags); for (Character flag : booleanFlags) { allFlagsBuilder.put(flag, "true"); } this.parsedArgs = ImmutableList.copyOf(parsedArgs); this.originalArgIndices = ImmutableList.copyOf(originalArgIndices); this.booleanFlags = ImmutableSet.copyOf(booleanFlags); this.valueFlags = ImmutableMap.copyOf(valueFlags); this.allFlags = allFlagsBuilder.build(); this.suggestionContext = suggestionContext; }
public Builder setExpectedValueFlags(Set<Character> expectedValueFlags) { this.expectedValueFlags = ImmutableSet.copyOf(expectedValueFlags); return this; }