/*
* 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.beam.sdk.io.fs;
import java.io.Serializable;
import javax.annotation.Nullable;
import org.apache.beam.sdk.annotations.Experimental;
import org.apache.beam.sdk.annotations.Experimental.Kind;
import org.apache.beam.sdk.io.FileSystem;
import org.apache.beam.sdk.io.FileSystems;
import org.apache.beam.sdk.io.fs.ResolveOptions.StandardResolveOptions;
/**
* An identifier which represents a file-like resource.
*
* <p>{@link ResourceId} is hierarchical and composed of a sequence of directory
* and file name elements separated by a special separator or delimiter.
*
* <p>{@link ResourceId ResourceIds} are created using {@link FileSystems}. The two primary
* mechanisms are:
*
* <ul>
* <li>{@link FileSystems#match(java.util.List)}, which takes a list of {@link String} resource
* names or globs, queries the {@link FileSystem} for resources matching these specifications,
* and returns a {@link MatchResult} for each glob. This is typically used when reading from
* files.
*
* <li>{@link FileSystems#matchNewResource(String, boolean)}, which takes a {@link String} full
* resource name and type (file or directory) and generates a {@link FileSystem}-specific
* {@code ResourceId} for that resource. This call does not verify the presence or absence of that
* resource in the file system. This call is typically used when creating new directories or files
* to generate {@link ResourceId ResourceIds} for resources that may not yet exist.
* </ul>
*/
@Experimental(Kind.FILESYSTEM)
public interface ResourceId extends Serializable {
/**
* Returns a child {@code ResourceId} under {@code this}.
*
* <p>In order to write file system agnostic code, callers should not include delimiters
* in {@code other}, and should use {@link StandardResolveOptions} to specify
* whether to resolve a file or a directory.
*
* <p>For example:
*
* <pre>{@code
* ResourceId homeDir = ...;
* ResourceId tempOutput = homeDir
* .resolve("tempDir", StandardResolveOptions.RESOLVE_DIRECTORY)
* .resolve("output", StandardResolveOptions.RESOLVE_FILE);
* }</pre>
*
* <p>This {@link ResourceId} should represents a directory.
*
* <p>It is up to each file system to resolve in their own way.
*
* <p>Resolving special characters:
* <ul>
* <li>{@code resourceId.resolve("..", StandardResolveOptions.RESOLVE_DIRECTORY)} returns
* the parent directory of this {@code ResourceId}.
* <li>{@code resourceId.resolve("{@literal *}", StandardResolveOptions.RESOLVE_FILE)} returns
* a {@code ResourceId} which matches all files in this {@code ResourceId}.
* <li>{@code resourceId.resolve("{@literal *}", StandardResolveOptions.RESOLVE_DIRECTORY)}
* returns a {@code ResourceId} which matches all directories in this {@code ResourceId}.
* </ul>
*
* @throws IllegalStateException if this {@link ResourceId} is not a directory.
*
* @throws IllegalArgumentException if {@code other} contains illegal characters
* or is an illegal name. It is recommended that callers use common characters,
* such as {@code [_a-zA-Z0-9.-]}, in {@code other}.
*/
ResourceId resolve(String other, ResolveOptions resolveOptions);
/**
* Returns the {@code ResourceId} that represents the current directory of
* this {@code ResourceId}.
*
* <p>If it is already a directory, trivially returns this.
*/
ResourceId getCurrentDirectory();
/**
* Get the scheme which defines the namespace of the {@link ResourceId}.
*
* <p>The scheme is required to follow URI scheme syntax. See
* <a href="https://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>
*/
String getScheme();
/**
* Returns the name of the file or directory denoted by this {@code ResourceId}. The file name
* is the farthest element from the root in the directory hierarchy.
*
* @return a string representing the name of file or directory, or null if there are zero
* components.
*/
@Nullable String getFilename();
/**
* Returns {@code true} if this {@link ResourceId} represents a directory, false otherwise.
*/
boolean isDirectory();
/**
* Returns the string representation of this {@link ResourceId}.
*
* <p>The corresponding {@link FileSystem#match} is required to accept this string representation.
*/
String toString();
}