src/main/java/de/uapcore/lightpit/PathPattern.java

Mon, 04 Jan 2021 17:30:10 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 04 Jan 2021 17:30:10 +0100
changeset 178
88207b860cba
parent 130
7ef369744fd1
permissions
-rw-r--r--

automatically select version/component when creating new issues under active filters

     1 package de.uapcore.lightpit;
     3 import java.util.ArrayList;
     4 import java.util.List;
     6 public final class PathPattern {
     8     private final List<String> nodePatterns;
     9     private final boolean collection;
    11     /**
    12      * Constructs a new path pattern.
    13      * The special directories . and .. are disallowed in the pattern.
    14      *
    15      * @param pattern
    16      */
    17     public PathPattern(String pattern) {
    18         nodePatterns = parse(pattern);
    19         collection = pattern.endsWith("/");
    20     }
    22     private List<String> parse(String pattern) {
    24         var nodes = new ArrayList<String>();
    25         var parts = pattern.split("/");
    27         for (var part : parts) {
    28             if (part.isBlank()) continue;
    29             if (part.equals(".") || part.equals(".."))
    30                 throw new IllegalArgumentException("Path must not contain '.' or '..' nodes.");
    31             nodes.add(part);
    32         }
    34         return nodes;
    35     }
    37     /**
    38      * Matches a path against this pattern.
    39      * The path must be canonical in the sense that no . or .. parts occur.
    40      *
    41      * @param path the path to match
    42      * @return true if the path matches the pattern, false otherwise
    43      */
    44     public boolean matches(String path) {
    45         if (collection ^ path.endsWith("/"))
    46             return false;
    48         var nodes = parse(path);
    49         if (nodePatterns.size() != nodes.size())
    50             return false;
    52         for (int i = 0 ; i < nodePatterns.size() ; i++) {
    53             var pattern = nodePatterns.get(i);
    54             var node = nodes.get(i);
    55             if (pattern.startsWith("$"))
    56                 continue;
    57             if (!pattern.equals(node))
    58                 return false;
    59         }
    61         return true;
    62     }
    64     /**
    65      * Returns the path parameters found in the specified path using this pattern.
    66      * The return value of this method is undefined, if the patter does not match.
    67      *
    68      * @param path the path
    69      * @return the path parameters, if any, or an empty map
    70      * @see #matches(String)
    71      */
    72     public PathParameters obtainPathParameters(String path) {
    73         var params = new PathParameters();
    75         var nodes = parse(path);
    77         for (int i = 0 ; i < Math.min(nodes.size(), nodePatterns.size()) ; i++) {
    78             var pattern = nodePatterns.get(i);
    79             var node = nodes.get(i);
    80             if (pattern.startsWith("$")) {
    81                 params.put(pattern.substring(1), node);
    82             }
    83         }
    85         return params;
    86     }
    88     @Override
    89     public int hashCode() {
    90         var str = new StringBuilder();
    91         for (var node : nodePatterns) {
    92             if (node.startsWith("$")) {
    93                 str.append("/$");
    94             } else {
    95                 str.append('/');
    96                 str.append(node);
    97             }
    98         }
    99         if (collection)
   100             str.append('/');
   102         return str.toString().hashCode();
   103     }
   105     @Override
   106     public boolean equals(Object obj) {
   107         if (!obj.getClass().equals(PathPattern.class))
   108             return false;
   110         var other = (PathPattern) obj;
   111         if (collection ^ other.collection || nodePatterns.size() != other.nodePatterns.size())
   112             return false;
   114         for (int i = 0 ; i < nodePatterns.size() ; i++) {
   115             var left = nodePatterns.get(i);
   116             var right = other.nodePatterns.get(i);
   117             if (left.startsWith("$") && right.startsWith("$"))
   118                 continue;
   119             if (!left.equals(right))
   120                 return false;
   121         }
   123         return true;
   124     }
   125 }

mercurial