]> gerrit.simantics Code Review - simantics/platform.git/blob - graph/store/PathPattern.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / graph / store / PathPattern.java
1 package org.simantics.graph.store;
2
3 import gnu.trove.set.hash.THashSet;
4
5 import java.util.regex.Pattern;
6
7 import org.simantics.graph.query.Path;
8 import org.simantics.graph.query.PathChild;
9 import org.simantics.graph.query.Paths;
10
11 public class PathPattern {
12         
13         private static PathPattern EMPTY_PATTERN = new PathPattern(null, null);
14         
15         Path prefix;
16         Pattern suffix;
17         
18         private PathPattern(Path prefix, Pattern suffix) {
19                 this.prefix = prefix;
20                 this.suffix = suffix;
21         }
22
23         public static PathPattern compile(String pattern) {
24                 pattern = stripPatternPrefix(pattern);
25                 if(pattern == null)
26                         return EMPTY_PATTERN;
27                 String[] parts = pattern.split("/");
28                 
29                 Path path = Paths.Root;
30                 for(int i=0;i<parts.length;++i) {
31                         String part = parts[i];
32                         if(containsWildcards(part)) {
33                                 StringBuilder b = new StringBuilder(pattern.length());
34                                 for(;i<parts.length;++i) {
35                                         b.append('/');
36                                         b.append(parts[i]);
37                                 }
38                                 return new PathPattern(path, compileGlobPattern(b.toString()));
39                         }
40                         else
41                                 path = new PathChild(part, path);
42                 }
43                 
44                 return new PathPattern(path, null);
45         }
46         
47         private static String patternStart = "http://";
48         private static String stripPatternPrefix(String pattern) {
49                 for(int i=0;i<patternStart.length();++i) {
50                         if(pattern.length() <= i)
51                                 return null;
52                         char c = pattern.charAt(i);
53                         if(c == '*')
54                                 return pattern.substring(i);
55                         if(c != patternStart.charAt(i) && c != '?')
56                                 return null;
57                 }
58                 return pattern.substring(patternStart.length());
59         }
60         
61         private static boolean containsWildcards(String pattern) {
62                 return pattern.contains("*") || pattern.contains("?");
63         }
64         
65         private static Pattern compileGlobPattern(String pattern) {
66                 int length = pattern.length();
67                 StringBuilder b = new StringBuilder(2*length);
68                 b.append("\\Q");
69                 for(int i=0;i<length;++i) {
70                         char c = pattern.charAt(i);
71                         switch(c) {
72                         case '*':
73                                 b.append("\\E.*\\Q");
74                                 break;
75                         case '?':
76                                 b.append("\\E.\\Q");
77                                 break;
78                         case '\\':
79                                 ++i;
80                                 if(i < length) {
81                                         c = pattern.charAt(i);
82                                         if(c == '\\' && i+1 < length && pattern.charAt(i+1) == 'E') {
83                                                 ++i;
84                                                 b.append("\\E\\\\E\\Q");
85                                         }
86                                         else if(c == '*' || c == '?')
87                                                 b.append(c);
88                                         else {
89                                                 b.append('\\');
90                                                 b.append(c);
91                                         }
92                                 }
93                                 break;
94                         default:
95                                 b.append(c);
96                         }
97                 }
98                 b.append("\\E");
99                 return Pattern.compile(b.toString());
100         }
101         
102         @Override
103         public String toString() {
104                 return "(" + prefix + ", " + suffix + ")";
105         }
106         
107         public void search(IdentityStore store, THashSet<Path> result) {
108                 int id = store.pathToId(prefix);
109                 if(id == -1)
110                         return;
111                 store.findChildren(id, prefix, "", suffix, result);
112         }
113         
114         public static void main(String[] args) {
115                 System.out.println(compile("http://www.simantics.org/*/foo"));
116         }
117 }