com.facebook.buck.apple.xcode.xcconfig.TokenValue.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.apple.xcode.xcconfig.TokenValue.java

Source

/*
 * Copyright 2013-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.apple.xcode.xcconfig;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;

import java.util.Objects;

import javax.annotation.Nullable;

/**
 * A piece of value for an entry in a xcconfig file
 */
public class TokenValue {
    enum Type {
        /** literal strings */
        LITERAL,
        /** reference to another value by its name */
        INTERPOLATION,
    }

    public final Type type;
    @Nullable
    public final String literalValue;
    @Nullable
    public final ImmutableList<TokenValue> interpolationValue;

    private TokenValue(Type type, @Nullable String literalValue,
            @Nullable ImmutableList<TokenValue> interpolationValue) {
        this.type = type;
        this.literalValue = literalValue;
        this.interpolationValue = interpolationValue;
    }

    public static TokenValue literal(String value) {
        return new TokenValue(Type.LITERAL, value, null);
    }

    public static TokenValue interpolation(ImmutableList<TokenValue> value) {
        return new TokenValue(Type.INTERPOLATION, null, value);
    }

    public static TokenValue interpolation(String name) {
        return interpolation(ImmutableList.of(TokenValue.literal(name)));
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof TokenValue)) {
            return false;
        }

        TokenValue that = (TokenValue) other;
        return Objects.equals(this.type, that.type) && Objects.equals(this.literalValue, that.literalValue)
                && Objects.equals(this.interpolationValue, that.interpolationValue);
    }

    @Override
    public int hashCode() {
        return Objects.hash(type, literalValue, interpolationValue);
    }

    @Override
    public String toString() {
        switch (type) {
        case LITERAL:
            return literalValue;
        case INTERPOLATION:
            return "$(" + Joiner.on("").join(interpolationValue) + ")";
        }
        // unreachable
        throw new IllegalStateException("'type' should always be of type 'LITERAL' or 'INTERPOLATION'");
    }

    // Interpolate this token in depth using the given interpretation function
    public TokenValue interpolate(Function<String, Optional<TokenValue>> function) {
        switch (type) {
        case LITERAL:
            return this;

        case INTERPOLATION:
            ImmutableList<TokenValue> newValue = interpolateList(function, interpolationValue);
            if (newValue.size() == 1 && newValue.get(0).type == Type.LITERAL) {
                Optional<TokenValue> interpolated = function.apply(newValue.get(0).literalValue);
                if (interpolated.isPresent()) {
                    return interpolated.get();
                }
            }
            return interpolation(newValue);
        }
        // unreachable
        throw new IllegalStateException("'type' should always be of type 'LITERAL' or 'INTERPOLATION'");
    }

    // Interpolate the given list of tokens in depth using the given interpretation function
    // Take a chance to collapse a list made of string literals into a singleton literal
    public static ImmutableList<TokenValue> interpolateList(Function<String, Optional<TokenValue>> function,
            ImmutableList<TokenValue> values) {
        ImmutableList.Builder<TokenValue> newValues = ImmutableList.builder();
        @Nullable
        StringBuilder stringValue = new StringBuilder();

        for (TokenValue token : values) {
            TokenValue newToken = token.interpolate(function);

            newValues.add(newToken);

            if (stringValue != null) {
                if (newToken.type != Type.LITERAL) {
                    stringValue = null;
                } else {
                    stringValue.append(newToken.literalValue);
                }
            }
        }

        if (stringValue != null) {
            return ImmutableList.of(literal(stringValue.toString()));
        }
        return newValues.build();
    }

}