com.facebook.buck.rules.modern.impl.StringifyingValueVisitor.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.rules.modern.impl.StringifyingValueVisitor.java

Source

/*
 * Copyright 2018-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.modern.impl;

import com.facebook.buck.core.model.EmptyTargetConfiguration;
import com.facebook.buck.core.model.TargetConfiguration;
import com.facebook.buck.core.rulekey.AddsToRuleKey;
import com.facebook.buck.core.rules.modern.annotations.CustomFieldBehavior;
import com.facebook.buck.core.sourcepath.SourcePath;
import com.facebook.buck.io.file.MorePaths;
import com.facebook.buck.rules.modern.ClassInfo;
import com.facebook.buck.rules.modern.OutputPath;
import com.facebook.buck.rules.modern.ValueTypeInfo;
import com.facebook.buck.rules.modern.ValueVisitor;
import com.facebook.buck.util.Scope;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;

/** A ValueVisitor that can be used to construct a String representation of an object. */
public class StringifyingValueVisitor implements ValueVisitor<RuntimeException> {
    private StringBuilder builder = new StringBuilder();
    private int indent = 0;

    @Override
    public void visitOutputPath(OutputPath value) {
        append("OutputPath(%s)", MorePaths.pathWithUnixSeparators(OutputPath.internals().getPath(value)));
    }

    @Override
    public void visitSourcePath(SourcePath value) {
        append("SourcePath(%s)", value.toString().replace('\\', '/'));
    }

    @Override
    public <T> void visitField(Field field, T value, ValueTypeInfo<T> valueTypeInfo,
            Optional<CustomFieldBehavior> customBehavior) {
        newline();
        append("%s:", field.getName());
        valueTypeInfo.visit(value, this);
    }

    private <T> void visitIterableValues(Iterable<T> value, ValueTypeInfo<T> innerType) {
        for (T e : value) {
            newline();
            innerType.visit(e, this);
        }
    }

    @Override
    public <T> void visitSet(ImmutableSet<T> value, ValueTypeInfo<T> innerType) throws RuntimeException {
        container("Set", () -> visitIterableValues(value, innerType));
    }

    @Override
    public <T> void visitSortedSet(ImmutableSortedSet<T> value, ValueTypeInfo<T> innerType) {
        container("SortedSet", () -> visitIterableValues(value, innerType));
    }

    @Override
    public <K, V> void visitMap(ImmutableMap<K, V> value, ValueTypeInfo<K> keyType, ValueTypeInfo<V> valueType)
            throws RuntimeException {
        container("Map", () -> visitMapValues(value, keyType, valueType));
    }

    @Override
    public <K, V> void visitSortedMap(ImmutableSortedMap<K, V> value, ValueTypeInfo<K> keyType,
            ValueTypeInfo<V> valueType) {
        container("SortedMap", () -> visitMapValues(value, keyType, valueType));
    }

    private <K, V> void visitMapValues(ImmutableMap<K, V> value, ValueTypeInfo<K> keyType,
            ValueTypeInfo<V> valueType) {
        for (Map.Entry<K, V> e : value.entrySet()) {
            newline();
            container("key", () -> {
                newline();
                keyType.visit(e.getKey(), this);
            });
            newline();
            container("value", () -> {
                newline();
                valueType.visit(e.getValue(), this);
            });
        }
    }

    @Override
    public <T> void visitList(ImmutableList<T> value, ValueTypeInfo<T> innerType) {
        container("List", () -> visitIterableValues(value, innerType));
    }

    @Override
    public <T> void visitOptional(Optional<T> value, ValueTypeInfo<T> innerType) {
        if (value.isPresent()) {
            container("Optional", () -> {
                newline();
                innerType.visit(value.get(), this);
            });
        } else {
            append("Optional.empty()");
        }
    }

    @Override
    public <T> void visitNullable(@Nullable T value, ValueTypeInfo<T> inner) throws RuntimeException {
        if (value == null) {
            append("null");
        } else {
            inner.visit(value, this);
        }
    }

    @Override
    public <T extends AddsToRuleKey> void visitDynamic(T value, ClassInfo<T> classInfo) throws RuntimeException {
        container(String.format("%s", value.getClass().getName()), () -> {
            classInfo.visit(value, this);
        });
    }

    @Override
    public void visitString(String value) {
        append("string(%s)", value);
    }

    @Override
    public void visitCharacter(Character value) {
        append("character(%s)", value);
    }

    @Override
    public void visitBoolean(Boolean value) {
        append("boolean(%s)", value);
    }

    @Override
    public void visitByte(Byte value) {
        append("byte(%s)", value);
    }

    @Override
    public void visitShort(Short value) {
        append("short(%s)", value);
    }

    @Override
    public void visitInteger(Integer value) {
        append("integer(%s)", value);
    }

    @Override
    public void visitLong(Long value) {
        append("long(%s)", value);
    }

    @Override
    public void visitFloat(Float value) {
        append("float(%s)", value);
    }

    @Override
    public void visitDouble(Double value) {
        append("double(%s)", value);
    }

    @Override
    public void visitTargetConfiguration(TargetConfiguration value) throws RuntimeException {
        if (value instanceof EmptyTargetConfiguration) {
            append("configuration()");
        } else {
            throw new IllegalStateException();
        }
    }

    private void container(String label, Runnable runner) {
        append("%s<", label);
        indent++;
        try (Scope ignored = () -> {
            indent--;
            newline();
            append(">");
        }) {
            runner.run();
        }
    }

    private void append(String value) {
        builder.append(value);
    }

    private void append(String format, Object... args) {
        builder.append(String.format(format, args));
    }

    private void newline() {
        append("\n");
        for (int i = 0; i < indent; i++) {
            append("  ");
        }
    }

    public String getValue() {
        return builder.toString().trim();
    }

    @Override
    public void visitPath(Path path) {
        append("path(%s)", MorePaths.pathWithUnixSeparators(path));
    }
}