All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hadoop.fs.impl.FlagSet Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hadoop.fs.impl;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.StreamCapabilities;
import org.apache.hadoop.util.ConfigurationHelper;
import org.apache.hadoop.util.Preconditions;

import static java.util.Objects.requireNonNull;
import static org.apache.hadoop.util.ConfigurationHelper.mapEnumNamesToValues;

/**
 * A set of flags, constructed from a configuration option or from a string,
 * with the semantics of
 * {@link ConfigurationHelper#parseEnumSet(String, String, Class, boolean)}
 * and implementing {@link StreamCapabilities}.
 * 

* Thread safety: there is no synchronization on a mutable {@code FlagSet}. * Once declared immutable, flags cannot be changed, so they * becomes implicitly thread-safe. */ public final class FlagSet> implements StreamCapabilities { /** * Class of the enum. * Used for duplicating the flags as java type erasure * loses this information otherwise. */ private final Class enumClass; /** * Prefix for path capabilities probe. */ private final String prefix; /** * Set of flags. */ private final EnumSet flags; /** * Is the set immutable? */ private final AtomicBoolean immutable = new AtomicBoolean(false); /** * Mapping of prefixed flag names to enum values. */ private final Map namesToValues; /** * Create a FlagSet. * @param enumClass class of enum * @param prefix prefix (with trailing ".") for path capabilities probe * @param flags flags. A copy of these are made. */ private FlagSet(final Class enumClass, final String prefix, @Nullable final EnumSet flags) { this.enumClass = requireNonNull(enumClass, "null enumClass"); this.prefix = requireNonNull(prefix, "null prefix"); this.flags = flags != null ? EnumSet.copyOf(flags) : EnumSet.noneOf(enumClass); this.namesToValues = mapEnumNamesToValues(prefix, enumClass); } /** * Get a copy of the flags. *

* This is immutable. * @return the flags. */ public EnumSet flags() { return EnumSet.copyOf(flags); } /** * Probe for the FlagSet being empty. * @return true if there are no flags set. */ public boolean isEmpty() { return flags.isEmpty(); } /** * Is a flag enabled? * @param flag flag to check * @return true if it is in the set of enabled flags. */ public boolean enabled(final E flag) { return flags.contains(flag); } /** * Check for mutability before any mutating operation. * @throws IllegalStateException if the set is still mutable */ private void checkMutable() { Preconditions.checkState(!immutable.get(), "FlagSet is immutable"); } /** * Enable a flag. * @param flag flag to enable. */ public void enable(final E flag) { checkMutable(); flags.add(flag); } /** * Disable a flag. * @param flag flag to disable */ public void disable(final E flag) { checkMutable(); flags.remove(flag); } /** * Set a flag to the chosen value. * @param flag flag * @param state true to enable, false to disable. */ public void set(final E flag, boolean state) { if (state) { enable(flag); } else { disable(flag); } } /** * Is a flag enabled? * @param capability string to query the stream support for. * @return true if the capability maps to an enum value and * that value is set. */ @Override public boolean hasCapability(final String capability) { final E e = namesToValues.get(capability); return e != null && enabled(e); } /** * Make immutable; no-op if already set. */ public void makeImmutable() { immutable.set(true); } /** * Is the FlagSet immutable? * @return true iff the FlagSet is immutable. */ public boolean isImmutable() { return immutable.get(); } /** * Get the enum class. * @return the enum class. */ public Class getEnumClass() { return enumClass; } @Override public String toString() { return "{" + (flags.stream() .map(Enum::name) .collect(Collectors.joining(", "))) + "}"; } /** * Generate the list of capabilities. * @return a possibly empty list. */ public List pathCapabilities() { return namesToValues.keySet().stream() .filter(this::hasCapability) .collect(Collectors.toList()); } /** * Equality is based on the value of {@link #enumClass} and * {@link #prefix} and the contents of the set, which must match. *

* The immutability flag is not considered, nor is the * {@link #namesToValues} map, though as that is generated from * the enumeration and prefix, it is implicitly equal if the prefix * and enumClass fields are equal. * @param o other object * @return true iff the equality condition is met. */ @Override public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } FlagSet flagSet = (FlagSet) o; return Objects.equals(enumClass, flagSet.enumClass) && Objects.equals(prefix, flagSet.prefix) && Objects.equals(flags, flagSet.flags); } /** * Hash code is based on the flags. * @return a hash code. */ @Override public int hashCode() { return Objects.hashCode(flags); } /** * Create a copy of the FlagSet. * @return a new mutable instance with a separate copy of the flags */ public FlagSet copy() { return new FlagSet<>(enumClass, prefix, flags); } /** * Convert to a string which can be then set in a configuration. * This is effectively a marshalled form of the flags. * @return a comma separated list of flag names. */ public String toConfigurationString() { return flags.stream() .map(Enum::name) .collect(Collectors.joining(", ")); } /** * Create a FlagSet. * @param enumClass class of enum * @param prefix prefix (with trailing ".") for path capabilities probe * @param flags flags * @param enum type * @return a mutable FlagSet */ public static > FlagSet createFlagSet( final Class enumClass, final String prefix, final EnumSet flags) { return new FlagSet<>(enumClass, prefix, flags); } /** * Create a FlagSet from a list of enum values. * @param enumClass class of enum * @param prefix prefix (with trailing ".") for path capabilities probe * @param enabled varags list of flags to enable. * @param enum type * @return a mutable FlagSet */ @SafeVarargs public static > FlagSet createFlagSet( final Class enumClass, final String prefix, final E... enabled) { final FlagSet flagSet = new FlagSet<>(enumClass, prefix, null); Arrays.stream(enabled).forEach(flag -> { if (flag != null) { flagSet.enable(flag); } }); return flagSet; } /** * Build a FlagSet from a comma separated list of values. * Case independent. * Special handling of "*" meaning: all values. * @param enumClass class of enum * @param conf configuration * @param key key to look for * @param ignoreUnknown should unknown values raise an exception? * @param enumeration type * @return a mutable FlagSet * @throws IllegalArgumentException if one of the entries was unknown and ignoreUnknown is false, * or there are two entries in the enum which differ only by case. */ public static > FlagSet buildFlagSet( final Class enumClass, final Configuration conf, final String key, final boolean ignoreUnknown) { final EnumSet flags = conf.getEnumSet(key, enumClass, ignoreUnknown); return createFlagSet(enumClass, key + ".", flags); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy