com.expedia.tesla.compiler.Util.java Source code

Java tutorial

Introduction

Here is the source code for com.expedia.tesla.compiler.Util.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Expedia 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.expedia.tesla.compiler;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.io.FileUtils;

import com.expedia.tesla.schema.Schema;
import com.expedia.tesla.schema.UserType;

/**
 * Tesla compiler utility methods.
 * 
 * @author <a href="mailto:yzuo@expedia.com">Yunfei Zuo</a>
 */
public class Util {
    /**
     * Convert a list of elements to a single comma separated string.
     * 
     * @param list
     *       the collection of values to join together.
     * 
     * @return
     *       a single comma separated string.
     */
    public static <T> String commaSeparate(Collection<T> list) {
        return delimiterSeparate(list, ", ");
    }

    /**
     * Convert a list of elements to a single delimiter separated string.
     * 
     * @param list
     *       the collection of values to join together.
     * @param delimiter
     *       the delimiter that separates values.
     * 
     * @return
     *       a single delimiter separated string.
     */
    public static <T> String delimiterSeparate(Collection<T> list, String delimiter) {
        StringBuilder sb = new StringBuilder();
        for (T e : list) {
            if (sb.length() > 0) {
                sb.append(delimiter);
            }
            sb.append(e.toString());
        }
        return sb.toString();
    }

    /**
     * Make the first character lower case. 
     * <p>
     * The input string must at least has 2 characters.
     * 
     * @param s
     *       the input string value.
     * @return
     *       the string with first character lower case.
     */
    public static String firstCharLowerCase(String s) {
        return s.substring(0, 1).toLowerCase() + s.substring(1);
    }

    /**
     * Make the first character upper case. 
     * <p>
     * The input string must at least has 2 characters.
     * 
     * @param s
     *       the input string value.
     * @return
     *       the string with first character upper case.
     */
    public static String firstCharUpperCase(String s) {
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
     * Extract short name from a full qualified type name.
     * <p>
     * The full name has the format of {@code namespace.typename}. 
     * 
     * @param fullName
     *       full type name.
     * 
     * @return
     *       short name.
     */
    public static String toShortName(String fullName) {
        return UserType.toShortName(fullName);
    }

    /**
     * Extract name space from a full qualified type name.
     * <p>
     * The full name has the format of {@code namespace.typename}. 
     * 
     * @param fullName
     *       full type name.
     * 
     * @return
     *       name space.
     */
    public static String toNameSpace(String fullName) {
        return UserType.toNameSpace(fullName);
    }

    /**
     * Get a new line character.
     * 
     * @return
     *       a new line character.
     */
    public static String getNewLine() {
        return "\n";
    }

    /**
     * Get a set of all user types defined in all schemas. It's the union of all
     * user type definitions.
     * 
     * @param schemas
     *            A collection of Tesla schema objects.
     * @return A set of all user types defined in all schemas
     */
    public static Collection<UserType> getAllUserTypes(Collection<Schema> schemas) {
        Map<String, UserType> all = new TreeMap<String, UserType>();
        for (Schema schema : schemas) {
            for (UserType t : schema.getUserTypes()) {
                all.put(t.getName(), t);
            }
        }
        return all.values();
    }

    /**
     * Expand glob file patterns to path strings. Any path element that is not a glob pattern will be keep as it is.
     * 
     * @param pathOrPatterns
     *       glob patterns.
     * 
     * @return
     *       The expanded paths.
     * 
     * @throws IOException
     *       On IO errors.
     */
    public static Collection<String> expandWildcard(Collection<String> pathOrPatterns) throws IOException {
        final List<String> files = new ArrayList<String>();
        final List<PathMatcher> matchers = new ArrayList<PathMatcher>();
        for (String pattern : pathOrPatterns) {
            if (pattern.contains("*") || pattern.contains("?")) {
                PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
                matchers.add(matcher);
            } else {
                files.add(pattern);
            }
        }

        if (!matchers.isEmpty()) {
            Files.walkFileTree(new File(System.getProperty("user.dir")).toPath(), new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
                    for (PathMatcher matcher : matchers) {
                        if (matcher.matches(file)) {
                            files.add(file.toString());
                        }
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        }

        return files;
    }

    /**
     * Parse a Java {@code classpath} string to URLs. The {@code classpath} is represented with the same format of the 
     * {@code CLASSPATH} variable or {@code -cp} java option. It supports the {@code *} wildcard.
     * 
     * @param classpath
     *       the classpath string.
     * @return
     *       URLs.
     * 
     * @throws IOException
     *       on IO errors.
     */
    public static URL[] parseClassPath(String classpath) throws IOException {
        final String splitPattern = Character.toString(File.pathSeparatorChar);
        final String wildcardPattern = ".+\\*";
        String[] paths = classpath.split(splitPattern);
        List<URL> urls = new ArrayList<URL>();
        for (String path : paths) {
            path = path.trim();
            if (path.matches(wildcardPattern)) {
                File folder = new File(path.replace("\\*", ""));
                if (folder.exists()) {
                    File[] files = folder.listFiles();
                    for (File f : files) {
                        urls.add(f.toURI().toURL());
                    }
                }
            } else {
                urls.add(new File(path).toURI().toURL());
            }
        }
        URL[] result = new URL[urls.size()];
        return urls.toArray(result);
    }

    /**
     * Load a Java class by it's full name.
     * 
     * @param name
     *            The full name of the Java class to load.
     * @param classpath
     *            The class paths or jar files from where the Java class be
     *            loaded. If this is null or empty string. {@code loadClass}
     *            will try to load from JVM classpath instead.
     * @return The java.lang.Class object represents the Java class.
     * @throws ClassNotFoundException
     *             If the class is not found.
     * @throws IOException
     *             If the jar file cannot open.
     */
    public static java.lang.Class<?> loadClass(String name, String classpath)
            throws ClassNotFoundException, IOException {
        return loadClass(name, (classpath == null || classpath.isEmpty()) ? null : parseClassPath(classpath));
    }

    /**
     * Load a Java class by it's full name.
     * 
     * @param name
     *            The full name of the Java class to load.
     * @param urls
     *            An array of URL objects represent class paths or jar files.
     * @return The java.lang.Class object represents the Java class.
     * @throws ClassNotFoundException
     *             If the class is not found.
     * @throws IOException
     *             If the jar file cannot open.
     */
    public static java.lang.Class<?> loadClass(String name, URL[] urls) throws ClassNotFoundException, IOException {
        java.lang.Class<?> clzz = null;
        if (urls != null && urls.length > 0) {
            URLClassLoader cl = URLClassLoader.newInstance(urls, Util.class.getClassLoader());
            clzz = cl.loadClass(name);
        }

        if (clzz == null) {
            clzz = Class.forName(name);
        }

        return clzz;
    }

    /**
    * Makes any necessary but nonexistent parent directories for a given File. If the parent directory cannot be
    * created then an IOException is thrown. 
    * <p>
    * Workaround for {@code FileUtils.forceMkdirParent} in Apache Commons IO 2.5.
    *
    * @param file
    *            file with parent to create, must not be {@code null}
    * @throws NullPointerException
    *             if the file is {@code null}
    * @throws IOException
    *             if the parent directory cannot be created
    * @see <a herf="http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#forceMkdirParent(java.io.File)">FileUtils.forceMkdirParent</a>
    */
    public static void forceMkdirParent(final File file) throws IOException {
        final File parent = file.getParentFile();
        if (parent == null) {
            return;
        }
        FileUtils.forceMkdir(parent);
    }
}