OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 67 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 67 Rev 83
Line 21... Line 21...
21
import java.util.Collections;
21
import java.util.Collections;
22
import java.util.List;
22
import java.util.List;
23
import java.util.regex.Matcher;
23
import java.util.regex.Matcher;
24
import java.util.regex.Pattern;
24
import java.util.regex.Pattern;
25
 
25
 
-
 
26
import net.jcip.annotations.Immutable;
-
 
27
 
26
/**
28
/**
27
 * A dotted SQL name, eg "table.field" or "schema.table".
29
 * A dotted SQL name, eg "table.field" or "schema.table".
28
 * 
30
 * 
29
 * @author Sylvain
31
 * @author Sylvain
30
 */
32
 */
-
 
33
@Immutable
31
public final class SQLName {
34
public final class SQLName {
32
 
35
 
33
    private static final Pattern unquoted = Pattern.compile("\\w+");
36
    private static final Pattern unquoted = Pattern.compile("\\w+");
-
 
37
    private static final Pattern MS_END_QUOTE = Pattern.compile("]", Pattern.LITERAL);
34
 
38
 
35
    /**
39
    /**
36
     * Parse a possibly quoted string to an SQL name.
40
     * Parse a possibly quoted string to an SQL name.
37
     * 
41
     * 
38
     * @param name a String, eg public."ta.ble seq".
42
     * @param name a String, eg public."ta.ble seq".
39
     * @return the corresponding SQL name, eg "public"."ta.ble seq".
43
     * @return the corresponding SQL name, eg "public"."ta.ble seq".
40
     */
44
     */
41
    public static SQLName parse(String name) {
45
    public static SQLName parse(String name) {
-
 
46
        return parse(name, '"', '"');
-
 
47
    }
-
 
48
 
-
 
49
    public static SQLName parseMS(String name) {
-
 
50
        // lucky for us, the rules are the same as for standard SQL
-
 
51
        return parse(name, '[', ']');
-
 
52
    }
-
 
53
 
-
 
54
    private static SQLName parse(String name, final char startQuote, final char endQuote) {
42
        name = name.trim();
55
        name = name.trim();
43
        final List<String> res = new ArrayList<String>();
56
        final List<String> res = new ArrayList<String>();
44
        int index = 0;
57
        int index = 0;
45
        while (index < name.length()) {
58
        while (index < name.length()) {
46
            final char c = name.charAt(index);
59
            final char c = name.charAt(index);
47
            final boolean inQuote = c == '"';
60
            final boolean inQuote = c == startQuote;
48
            if (inQuote) {
61
            if (inQuote) {
49
                // pass the opening quote
62
                // pass the opening quote
50
                index += 1;
63
                index += 1;
51
                int index2 = findNextQuote(name, index);
64
                int index2 = findNextQuote(name, index, endQuote);
52
                // handle escaped "
65
                // handle escaped "
53
                String part = "";
66
                String part = "";
54
                // while the char after " is also "
67
                // while the char after " is also "
55
                while ((index2 + 1) < name.length() && name.charAt(index2 + 1) == '"') {
68
                while ((index2 + 1) < name.length() && name.charAt(index2 + 1) == endQuote) {
56
                    // index2+1 to keep the first quote
69
                    // index2+1 to keep the first quote
57
                    part += name.substring(index, index2 + 1);
70
                    part += name.substring(index, index2 + 1);
58
                    // pass ""
71
                    // pass ""
59
                    index = index2 + 2;
72
                    index = index2 + 2;
60
                    index2 = findNextQuote(name, index);
73
                    index2 = findNextQuote(name, index, endQuote);
61
                }
74
                }
62
                part += name.substring(index, index2);
75
                part += name.substring(index, index2);
63
                res.add(part);
76
                res.add(part);
64
                // pass the closing quote
77
                // pass the closing quote
65
                index = index2 + 1;
78
                index = index2 + 1;
Line 82... Line 95...
82
        }
95
        }
83
 
96
 
84
        return new SQLName(res);
97
        return new SQLName(res);
85
    }
98
    }
86
 
99
 
87
    private static int findNextQuote(final String name, final int index) {
100
    private static int findNextQuote(final String name, final int index, final char c) {
88
        final int res = name.indexOf('"', index);
101
        final int res = name.indexOf(c, index);
89
        if (res < 0)
102
        if (res < 0)
90
            throw new IllegalArgumentException("no corresponding quote " + index);
103
            throw new IllegalArgumentException("no corresponding quote " + index);
91
        return res;
104
        return res;
92
    }
105
    }
93
 
106
 
94
    final List<String> items;
107
    private final List<String> items;
95
 
108
 
96
    public SQLName(String... items) {
109
    public SQLName(String... items) {
97
        this(Arrays.asList(items));
110
        this(Arrays.asList(items));
98
    }
111
    }
99
 
112
 
Line 103... Line 116...
103
     * (e.g. in H2 the JDBC name is "", but cannot be used in SQL queries).
116
     * (e.g. in H2 the JDBC name is "", but cannot be used in SQL queries).
104
     * 
117
     * 
105
     * @param items the names.
118
     * @param items the names.
106
     */
119
     */
107
    public SQLName(List<String> items) {
120
    public SQLName(List<String> items) {
-
 
121
        this(items, false);
-
 
122
    }
-
 
123
 
-
 
124
    private SQLName(List<String> items, final boolean safe) {
108
        super();
125
        super();
-
 
126
        if (safe) {
-
 
127
            this.items = items;
-
 
128
        } else {
109
        this.items = new ArrayList<String>(items.size());
129
            final List<String> tmp = new ArrayList<String>(items.size());
110
        for (final String item : items) {
130
            for (final String item : items) {
111
            if (item != null && item.length() > 0)
131
                if (item != null && item.length() > 0)
112
                this.items.add(item);
132
                    tmp.add(item);
-
 
133
            }
-
 
134
            this.items = Collections.unmodifiableList(tmp);
113
        }
135
        }
114
    }
136
    }
115
 
137
 
116
    /**
138
    /**
117
     * Return the quoted form, eg for table.field : "table"."field".
139
     * Return the quoted form, eg for table.field : "table"."field".
Line 124... Line 146...
124
                return SQLBase.quoteIdentifier(input);
146
                return SQLBase.quoteIdentifier(input);
125
            }
147
            }
126
        });
148
        });
127
    }
149
    }
128
 
150
 
-
 
151
    public String quoteMS() {
-
 
152
        return CollectionUtils.join(this.items, ".", new ITransformer<String, String>() {
-
 
153
            public String transformChecked(String input) {
-
 
154
                return '[' + MS_END_QUOTE.matcher(input).replaceAll("]]") + ']';
-
 
155
            }
-
 
156
        });
-
 
157
    }
-
 
158
 
129
    /**
159
    /**
130
     * Return the item at the given index. You can use negatives to count backwards (ie -1 is the
160
     * Return the item at the given index. You can use negatives to count backwards (ie -1 is the
131
     * last item).
161
     * last item).
132
     * 
162
     * 
133
     * @param index an int between 0 and count - 1, or between -count and -1.
163
     * @param index an int between 0 and count - 1, or between -count and -1.
Line 169... Line 199...
169
    public String getFirst() {
199
    public String getFirst() {
170
        return this.getItem(0);
200
        return this.getItem(0);
171
    }
201
    }
172
 
202
 
173
    public SQLName getRest() {
203
    public SQLName getRest() {
174
        return new SQLName(this.items.subList(1, this.items.size()));
204
        return new SQLName(this.items.subList(1, this.items.size()), true);
175
    }
205
    }
176
 
206
 
177
    /**
207
    /**
178
     * Resolve the passed name from this.
208
     * Resolve the passed name from this.
179
     * 
209
     * 
Line 188... Line 218...
188
            return to;
218
            return to;
189
        } else {
219
        } else {
190
            final List<String> l = new ArrayList<String>(fromCount);
220
            final List<String> l = new ArrayList<String>(fromCount);
191
            l.addAll(from.asList().subList(0, fromCount - toCount));
221
            l.addAll(from.asList().subList(0, fromCount - toCount));
192
            l.addAll(to.asList());
222
            l.addAll(to.asList());
193
            return new SQLName(l);
223
            return new SQLName(Collections.unmodifiableList(l), true);
194
        }
224
        }
195
    }
225
    }
196
 
226
 
197
    /**
227
    /**
198
     * The shortest SQLName to identify <code>to</code> from this.
228
     * The shortest SQLName to identify <code>to</code> from this.
Line 214... Line 244...
214
        assert fromCount == toCount;
244
        assert fromCount == toCount;
215
        final int common = CollectionUtils.equalsFromStart(from.asList(), to.asList());
245
        final int common = CollectionUtils.equalsFromStart(from.asList(), to.asList());
216
        if (common == 0) {
246
        if (common == 0) {
217
            return to;
247
            return to;
218
        } else {
248
        } else {
219
            return new SQLName(to.asList().subList(common, toCount));
249
            return new SQLName(to.asList().subList(common, toCount), true);
220
        }
250
        }
221
    }
251
    }
222
 
252
 
223
    public final List<String> asList() {
253
    public final List<String> asList() {
224
        return Collections.unmodifiableList(this.items);
254
        return this.items;
225
    }
255
    }
226
 
256
 
227
    @Override
257
    @Override
228
    public boolean equals(Object obj) {
258
    public boolean equals(Object obj) {
229
        if (obj instanceof SQLName) {
259
        if (obj instanceof SQLName) {