ReflectionUtils.java

/*
 * Copyright 2016 Providence Authors
 *
 * 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 net.morimekta.providence.reflect.util;

import net.morimekta.providence.descriptor.PDeclaredDescriptor;
import net.morimekta.util.Strings;

import javax.annotation.Nonnull;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Simple utility for type checking and matching.
 */
public class ReflectionUtils {
    /**
     * @param descriptor A declared type descriptor.
     * @return If this type was declared directly. If false, this is an auto
     *         -declared type, like service method request and response.
     */
    public static boolean isDeclaredType(PDeclaredDescriptor<?> descriptor) {
        return !descriptor.isAutoType();
    }

    @Deprecated
    public static boolean isThriftFile(@Nonnull File file) {
        return isThriftBasedFileSyntax(file.toPath());
    }

    @Deprecated
    public static boolean isThriftFile(@Nonnull String filePath) {
        return isThriftBasedFileSyntax(Paths.get(filePath));
    }

    @Deprecated
    public static boolean isProvidenceFile(@Nonnull File file) {
        return isProvidenceFile(file.toPath());
    }

    @Deprecated
    public static boolean isProvidenceFile(@Nonnull String filePath) {
        return isProvidenceFile(Paths.get(filePath));
    }

    @Nonnull
    @Deprecated
    public static String programNameFromPath(@Nonnull String filePath) {
        return programNameFromPath(Paths.get(filePath));
    }

    /**
     * Get file name without suffix.
     *
     * @param path The file path.
     * @return The file name without suffix.
     */
    @Nonnull
    protected static String getFileName(@Nonnull Path path) {
        if (path.getFileName() == null) return "";
        return path.getFileName()
                   .toString()
                   .replaceAll("([^.])\\.[^.]+$", "$1");
    }

    /**
     * Get file suffix. The file suffix is all that is not considered the file name.
     *
     * @param path The file path.
     * @return The suffix.
     */
    @Nonnull
    public static String getFileSuffix(@Nonnull Path path) {
        if (path.getFileName() == null) return "";
        return path.getFileName()
                   .toString()
                   .substring(getFileName(path).length());
    }

    public static boolean isThriftFileSuffix(@Nonnull String suffix) {
        return suffix.equalsIgnoreCase(".thrift") ||
               suffix.equalsIgnoreCase(".thr");
    }

    public static boolean isProvidenceFileSuffix(@Nonnull String suffix) {
        return suffix.equalsIgnoreCase(".providence") ||
               suffix.equalsIgnoreCase(".pvd");
    }

    public static boolean isProvidenceFile(@Nonnull Path file) {
        return isProvidenceFileSuffix(getFileSuffix(file));
    }

    public static boolean isApacheThriftFile(@Nonnull Path file) {
        return isThriftFileSuffix(getFileSuffix(file));
    }

    public static boolean isThriftBasedFileSyntax(@Nonnull Path file) {
        String suffix = getFileSuffix(file);
        return isThriftFileSuffix(suffix) || isProvidenceFileSuffix(suffix);
    }

    @Nonnull
    public static String programNameFromPath(@Nonnull Path filePath) {
        if (isThriftBasedFileSyntax(filePath)) {
            return getFileName(filePath).replaceAll("[^a-zA-Z0-9_]", "_");
        }
        return "";
    }

    @Nonnull
    public static String longestCommonPrefixPath(Collection<String> paths) {
        if (paths.size() == 0) throw new IllegalArgumentException("Empty paths");
        String prefix = paths.iterator().next();
        for (String s : paths) {
            int len = Strings.commonPrefix(s, prefix);
            if (len < prefix.length()) {
                prefix = prefix.substring(0, len);
            }
        }
        if (prefix.contains("/")) {
            return prefix.replaceAll("/[^/]*$", "/");
        }
        return "";
    }

    @Nonnull
    public static List<String> stripCommonPrefix(List<String> paths) {
        String prefix = longestCommonPrefixPath(paths);
        if (prefix.length() > 0) {
            return paths.stream()
                        .map(s -> s.substring(prefix.length()))
                        .collect(Collectors.toList());
        }
        return paths;
    }

    private ReflectionUtils() {}
}