mirror of
https://github.com/google/nomulus.git
synced 2025-05-19 18:59:35 +02:00
Import code from internal repository to git
This commit is contained in:
commit
0ef0c933d2
2490 changed files with 281594 additions and 0 deletions
105
java/com/google/domain/registry/util/SqlTemplate.java
Normal file
105
java/com/google/domain/registry/util/SqlTemplate.java
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// 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.domain.registry.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static com.google.domain.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/** SQL template variable substitution. */
|
||||
@Immutable
|
||||
public final class SqlTemplate {
|
||||
|
||||
private static final Pattern KEY_PATTERN = Pattern.compile("[A-Z][_A-Z0-9]*");
|
||||
|
||||
private static final Pattern SEARCH_PATTERN =
|
||||
Pattern.compile("(['\"]?)%(" + KEY_PATTERN + ")%(['\"]?)");
|
||||
|
||||
private static final CharMatcher LEGAL_SUBSTITUTIONS =
|
||||
CharMatcher.javaLetterOrDigit().or(CharMatcher.anyOf("-_.,: "));
|
||||
|
||||
/** Returns a new immutable SQL template builder object, for query parameter substitution. */
|
||||
public static SqlTemplate create(String template) {
|
||||
return new SqlTemplate(template, ImmutableMap.<String, String>of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key/value that should be substituted an individual variable in the template.
|
||||
*
|
||||
* <p>Your template variables should appear as follows: {@code WHERE foo = '%BAR%'} and you
|
||||
* would call {@code .put("BAR", "some value"} to safely substitute it with a value. Only
|
||||
* whitelisted characters (as defined by {@link #LEGAL_SUBSTITUTIONS}) are allowed in values.
|
||||
*
|
||||
* @param key uppercase string that can have digits and underscores
|
||||
* @param value substitution value, comprised of whitelisted characters
|
||||
* @throws IllegalArgumentException if key or value has bad chars or duplicate keys were added
|
||||
*/
|
||||
public SqlTemplate put(String key, String value) {
|
||||
checkArgument(KEY_PATTERN.matcher(key).matches(), "Bad substitution key: %s", key);
|
||||
checkArgument(LEGAL_SUBSTITUTIONS.matchesAllOf(value), "Illegal characters in %s", value);
|
||||
return new SqlTemplate(template, new ImmutableMap.Builder<String, String>()
|
||||
.putAll(substitutions)
|
||||
.put(key, value)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the freshly substituted SQL code.
|
||||
*
|
||||
* @throws IllegalArgumentException if any substitution variable is not found in the template,
|
||||
* or if there are any variable-like strings (%something%) left after substitution.
|
||||
*/
|
||||
public String build() {
|
||||
StringBuffer result = new StringBuffer(template.length());
|
||||
Set<String> found = new HashSet<>();
|
||||
Matcher matcher = SEARCH_PATTERN.matcher(template);
|
||||
while (matcher.find()) {
|
||||
String wholeMatch = matcher.group(0);
|
||||
String leftQuote = matcher.group(1);
|
||||
String key = matcher.group(2);
|
||||
String rightQuote = matcher.group(3);
|
||||
String value = substitutions.get(key);
|
||||
checkArgumentNotNull(value, "%%s% found in template but no substitution specified", key);
|
||||
checkArgument(leftQuote.equals(rightQuote), "Quote mismatch: %s", wholeMatch);
|
||||
matcher.appendReplacement(result, String.format("%s%s%s", leftQuote, value, rightQuote));
|
||||
found.add(key);
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
Set<String> remaining = difference(substitutions.keySet(), found);
|
||||
checkArgument(remaining.isEmpty(),
|
||||
"Not found in template: %s", Joiner.on(", ").join(remaining));
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private final String template;
|
||||
private final ImmutableMap<String, String> substitutions;
|
||||
|
||||
private SqlTemplate(String template, ImmutableMap<String, String> substitutions) {
|
||||
this.template = checkNotNull(template);
|
||||
this.substitutions = checkNotNull(substitutions);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue