/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed 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 com.facebook.buck.rules.coercer;
import com.facebook.buck.apple.xcode.xcodeproj.SourceTreePath;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.RuleKeyAppendable;
import com.facebook.buck.rules.RuleKeyObjectSink;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.util.OptionalCompat;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.io.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import org.immutables.value.Value;
/**
* Frameworks can be specified as either a path to a file, or a path prefixed by a build setting.
*/
@Value.Immutable
@BuckStyleImmutable
abstract class AbstractFrameworkPath
implements Comparable<AbstractFrameworkPath>, RuleKeyAppendable {
/** The type of framework entry this object represents. */
protected enum Type {
/** An Xcode style {@link SourceTreePath}. */
SOURCE_TREE_PATH,
/** A Buck style {@link SourcePath}. */
SOURCE_PATH,
}
@Value.Parameter
protected abstract Type getType();
@Value.Parameter
public abstract Optional<SourceTreePath> getSourceTreePath();
@Value.Parameter
public abstract Optional<SourcePath> getSourcePath();
public Iterable<BuildRule> getDeps(SourcePathRuleFinder ruleFinder) {
return ruleFinder.filterBuildRuleInputs(OptionalCompat.asSet(getSourcePath()));
}
public Path getFileName(Function<SourcePath, Path> resolver) {
switch (getType()) {
case SOURCE_TREE_PATH:
return getSourceTreePath().get().getPath().getFileName();
case SOURCE_PATH:
return Preconditions.checkNotNull(resolver.apply(getSourcePath().get())).getFileName();
default:
throw new RuntimeException("Unhandled type: " + getType());
}
}
public String getName(Function<SourcePath, Path> resolver) {
String fileName = getFileName(resolver).toString();
return Files.getNameWithoutExtension(fileName);
}
public static Path getUnexpandedSearchPath(
Function<SourcePath, Path> resolver,
Function<? super Path, Path> relativizer,
FrameworkPath input) {
return convertToPath(resolver, relativizer, input).getParent();
}
private static Path convertToPath(
Function<SourcePath, Path> resolver,
Function<? super Path, Path> relativizer,
FrameworkPath input) {
switch (input.getType()) {
case SOURCE_TREE_PATH:
return Paths.get(input.getSourceTreePath().get().toString());
case SOURCE_PATH:
return relativizer.apply(
Preconditions.checkNotNull(resolver.apply(input.getSourcePath().get())));
default:
throw new RuntimeException("Unhandled type: " + input.getType());
}
}
@Value.Check
protected void check() {
switch (getType()) {
case SOURCE_TREE_PATH:
Preconditions.checkArgument(getSourceTreePath().isPresent());
Preconditions.checkArgument(!getSourcePath().isPresent());
break;
case SOURCE_PATH:
Preconditions.checkArgument(!getSourceTreePath().isPresent());
Preconditions.checkArgument(getSourcePath().isPresent());
break;
default:
throw new RuntimeException("Unhandled type: " + getType());
}
}
@Override
public int compareTo(AbstractFrameworkPath o) {
if (this == o) {
return 0;
}
int typeComparisonResult = getType().ordinal() - o.getType().ordinal();
if (typeComparisonResult != 0) {
return typeComparisonResult;
}
switch (getType()) {
case SOURCE_TREE_PATH:
return getSourceTreePath().get().compareTo(o.getSourceTreePath().get());
case SOURCE_PATH:
return getSourcePath().get().compareTo(o.getSourcePath().get());
default:
throw new RuntimeException("Unhandled type: " + getType());
}
}
@Override
public void appendToRuleKey(RuleKeyObjectSink sink) {
sink.setReflectively("sourcePath", getSourcePath());
sink.setReflectively("sourceTree", getSourceTreePath().map(Object::toString));
}
public static FrameworkPath ofSourceTreePath(SourceTreePath sourceTreePath) {
return FrameworkPath.of(Type.SOURCE_TREE_PATH, Optional.of(sourceTreePath), Optional.empty());
}
public static FrameworkPath ofSourcePath(SourcePath sourcePath) {
return FrameworkPath.of(Type.SOURCE_PATH, Optional.empty(), Optional.of(sourcePath));
}
}