Package com.google.devtools.depan.java.bytecode.impl

Source Code of com.google.devtools.depan.java.bytecode.impl.PackageTreeBuilder

/*
* Copyright 2009 Google 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.google.devtools.depan.java.bytecode.impl;

import com.google.devtools.depan.filesystem.graph.DirectoryElement;
import com.google.devtools.depan.filesystem.graph.FileSystemRelation;
import com.google.devtools.depan.java.graph.JavaRelation;
import com.google.devtools.depan.java.graph.PackageElement;
import com.google.devtools.depan.model.GraphNode;
import com.google.devtools.depan.model.builder.DependenciesListener;

import java.io.File;

/**
* Create a tree structure for packages and their corresponding file-system
* directories.
*
* @author <a href="leeca@google.com">Lee Carver</a>
*/
public class PackageTreeBuilder {

  /** Dependency builder */
  private final DependenciesListener builder;

  private PackageElement packageNode;
  private DirectoryElement packageDir;

  /**
   * @param builder
   */
  public PackageTreeBuilder(DependenciesListener builder) {
    this.builder = builder;
  }

  /**
   * Install a package tree and its corresponding directory tree for
   * the package and tree defined by the argument.  For conventionally
   * structured packages, the @c{@code packageFile} will be a suffix of the
   * {@code treeFile}.  However, this is not required.  The {@code treeFile}
   * may be shorter then the {@code packageFile}, which lead to inferred
   * parent directories.  It may also contain directory names that do not
   * correspond to package names.  These "perverse" embeddings of packages
   * into trees can result in unexpected associations.
   *
   * @param packageFile full Java path for package
   * @param treeFile directory path that contains the package
   * @return {@code PackageElement} for {@code packageFile}
   */
  public PackageElement installPackageTree(
      File packageFile, File treeFile) {
    createPackageDir(packageFile, treeFile.getPath());
    PackageElement result = packageNode;

    createPackageParents(packageFile, treeFile);
    return result;
  }

  /**
   * Ascend both the package tree and directory tree, creating any dependencies
   * that are required.  If any package already exists, assume the rest of the
   * tree is complete and stop.
   *
   * @param packageFile path to a package
   * @param treeFile path to a directory
   */
  private void createPackageParents(File packageFile, File treeFile) {
    if (null == packageFile) {
      return;
    }

    TreeClimber treePath = new TreeClimber(treeFile);
    GraphNode lookupNode = builder.newNode(packageNode);

    // If the lookup is not the same node, then a node with that identity
    // already exists.  No need to add that package (or its parents) again.
    while (lookupNode == packageNode) {
      // Set up for parent of current entities
      packageFile = packageFile.getParentFile();
      treePath.ascendTree();

      // Never parent a named packaged with the unnamed package
      if (null == packageFile) {
        return;
      }

      PackageElement childNode = packageNode;
      DirectoryElement childDir = packageDir;

      createPackageDir(packageFile, treePath.getTreePath());

      builder.newDep(packageNode, childNode, JavaRelation.PACKAGE);
      builder.newDep(packageDir, childDir, FileSystemRelation.CONTAINS_DIR);
      lookupNode = builder.newNode(packageNode);
    }
  }

  /**
   * Create both a package and directory, and the container dependency
   * between them.
   *
   * @param packageFile path to package
   * @param treePath path to directory
   */
  private void createPackageDir(File packageFile, String treePath) {
    packageNode = createPackage(packageFile);

    packageDir = new DirectoryElement(treePath);
    builder.newDep(packageDir, packageNode, JavaRelation.PACKAGEDIR);
  }

  private PackageElement createPackage(File packageFile) {
    if (null == packageFile) {
      return createPackage("");
    }
    return createPackage(packageFile.getPath());
  }

  private PackageElement createPackage(String packagePath) {
    if (packagePath.isEmpty()) {
      return new PackageElement("<unnamed>");
    }

    return new PackageElement(packagePath.replace(File.separatorChar, '.'));
  }
}
TOP

Related Classes of com.google.devtools.depan.java.bytecode.impl.PackageTreeBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.