Coverage Report - com.puppycrawl.tools.checkstyle.checks.imports.PkgControl
 
Classes in this File Line Coverage Branch Coverage Complexity
PkgControl
100%
40/40
80%
24/30
3
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 package com.puppycrawl.tools.checkstyle.checks.imports;
 20  
 
 21  
 import com.google.common.collect.Lists;
 22  
 import java.util.LinkedList;
 23  
 import java.util.List;
 24  
 
 25  
 /**
 26  
  * Represents the a tree of guards for controlling whether packages are allowed
 27  
  * to be used. Each instance must have a single parent or be the root node.
 28  
  * Each instance may have zero or more children.
 29  
  *
 30  
  * @author Oliver Burn
 31  
  */
 32  1
 class PkgControl
 33  
 {
 34  
     /** List of {@link Guard} objects to check. */
 35  27
     private final LinkedList<Guard> mGuards = Lists.newLinkedList();
 36  
     /** List of children {@link PkgControl} objects. */
 37  27
     private final List<PkgControl> mChildren = Lists.newArrayList();
 38  
     /** The parent. Null indicates we are the root node. */
 39  
     private final PkgControl mParent;
 40  
     /** The full package name for the node. */
 41  
     private final String mFullPackage;
 42  
 
 43  
     /**
 44  
      * Construct a root node.
 45  
      * @param aPkgName the name of the package.
 46  
      */
 47  
     PkgControl(final String aPkgName)
 48  14
     {
 49  14
         assert aPkgName != null;
 50  14
         mParent = null;
 51  14
         mFullPackage = aPkgName;
 52  14
     }
 53  
 
 54  
     /**
 55  
      * Construct a child node.
 56  
      * @param aParent the parent node.
 57  
      * @param aSubPkg the sub package name.
 58  
      */
 59  
     PkgControl(final PkgControl aParent, final String aSubPkg)
 60  13
     {
 61  13
         assert aParent != null;
 62  13
         assert aSubPkg != null;
 63  13
         mParent = aParent;
 64  13
         mFullPackage = aParent.getFullPackage() + "." + aSubPkg;
 65  13
         mParent.mChildren.add(this);
 66  13
     }
 67  
 
 68  
     /**
 69  
      * Adds a guard to the node.
 70  
      * @param aThug the guard to be added.
 71  
      */
 72  
     void addGuard(final Guard aThug)
 73  
     {
 74  57
         mGuards.addFirst(aThug);
 75  57
     }
 76  
 
 77  
     /**
 78  
      * @return the full package name represented by the node.
 79  
      */
 80  
     String getFullPackage()
 81  
     {
 82  38
         return mFullPackage;
 83  
     }
 84  
 
 85  
     /**
 86  
      * Search down the tree to locate the finest match for a supplied package.
 87  
      * @param aForPkg the package to search for.
 88  
      * @return the finest match, or null if no match at all.
 89  
      */
 90  
     PkgControl locateFinest(final String aForPkg)
 91  
     {
 92  
         // Check if we are a match.
 93  
         // This algormithm should be improved to check for a trailing "."
 94  
         // or nothing following.
 95  21
         if (!aForPkg.startsWith(getFullPackage())) {
 96  7
             return null;
 97  
         }
 98  
 
 99  
         // Check if any of the children match.
 100  14
         for (PkgControl pc : mChildren) {
 101  8
             final PkgControl match = pc.locateFinest(aForPkg);
 102  8
             if (match != null) {
 103  6
                 return match;
 104  
             }
 105  2
         }
 106  
 
 107  
         // No match so I am the best there is.
 108  8
         return this;
 109  
     }
 110  
 
 111  
     /**
 112  
      * Returns whether a package is allowed to be used. The algorithm checks
 113  
      * with the current node for a result, and if none is found then calls
 114  
      * its parent looking for a match. This will recurse looking for match.
 115  
      * If there is no clear result then {@link AccessResult#UNKNOWN} is
 116  
      * returned.
 117  
      * @param aForImport the package to check on.
 118  
      * @param aInPkg the package doing the import.
 119  
      * @return an {@link AccessResult}.
 120  
      */
 121  
     AccessResult checkAccess(final String aForImport, final String aInPkg)
 122  
     {
 123  56
         final AccessResult retVal = localCheckAccess(aForImport, aInPkg);
 124  56
         if (retVal != AccessResult.UNKNOWN) {
 125  22
             return retVal;
 126  
         }
 127  34
         else if (mParent == null) {
 128  
             // we are the top, so default to not allowed.
 129  11
             return AccessResult.DISALLOWED;
 130  
         }
 131  
 
 132  23
         return mParent.checkAccess(aForImport, aInPkg);
 133  
     }
 134  
 
 135  
     /**
 136  
      * Checks whether any of the guards for this node control access to
 137  
      * a specified package.
 138  
      * @param aForImport the package to check.
 139  
      * @param aInPkg the package doing the import.
 140  
      * @return an {@link AccessResult}.
 141  
      */
 142  
     private AccessResult localCheckAccess(final String aForImport,
 143  
         final String aInPkg)
 144  
     {
 145  56
         for (Guard g : mGuards) {
 146  
             // Check if a Guard is only meant to be applied locally.
 147  104
             if (g.isLocalOnly() && !mFullPackage.equals(aInPkg)) {
 148  10
                 continue;
 149  
             }
 150  94
             final AccessResult result = g.verifyImport(aForImport);
 151  94
             if (result != AccessResult.UNKNOWN) {
 152  22
                 return result;
 153  
             }
 154  72
         }
 155  34
         return AccessResult.UNKNOWN;
 156  
     }
 157  
 }