blob: 75d382007f5b64947fccd905d45bf311b7179a5c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.rocketmq.schema.registry.storage.jdbc.common;
/**
* expression builder
*/
public class ExpressionBuilder {
private final IdentifierRules rules;
private final StringBuilder sb = new StringBuilder();
public ExpressionBuilder(IdentifierRules rules) {
this.rules = rules != null ? rules : IdentifierRules.DEFAULT;
}
public static ExpressionBuilder create() {
return new ExpressionBuilder(IdentifierRules.DEFAULT);
}
public static ExpressionBuilder create(IdentifierRules identifierRules) {
return new ExpressionBuilder(identifierRules);
}
/**
* Get a {@link Transform} that will quote just the column names.
*
* @return the transform; never null
*/
public static Transform<String> columnNames() {
return (builder, input) -> builder.appendColumnName(input);
}
public static Transform<String> columnNamesWith(final String appended) {
return (builder, input) -> {
builder.appendColumnName(input);
builder.append(appended);
};
}
/**
* Return a new ExpressionBuilder that escapes quotes with the specified prefix.
* This builder remains unaffected.
*
* @param prefix the prefix
* @return the new ExpressionBuilder, or this builder if the prefix is null or empty
*/
public ExpressionBuilder escapeQuotesWith(String prefix) {
if (prefix == null || prefix.isEmpty()) {
return this;
}
return new ExpressionBuilder(this.rules.escapeQuotesWith(prefix));
}
/**
* Append to this builder's expression the delimiter defined by this builder's
* {@link IdentifierRules}.
*
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendIdentifierDelimiter() {
sb.append(rules.identifierDelimiter());
return this;
}
/**
* Always append to this builder's expression the leading quote character(s) defined by this
* builder's {@link IdentifierRules}.
*
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendLeadingQuote() {
sb.append(rules.leadingQuoteString());
return this;
}
protected ExpressionBuilder appendTrailingQuote() {
sb.append(rules.trailingQuoteString());
return this;
}
public ExpressionBuilder appendStringQuote() {
sb.append("'");
return this;
}
/**
* Append to this builder's expression a string surrounded by single quote characters ({@code '}).
*
* @param name the object whose string representation is to be appended
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendStringQuoted(Object name) {
appendStringQuote();
sb.append(name);
appendStringQuote();
return this;
}
/**
* Append to this builder's expression the identifier.
*
* @param name the name to be appended
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendIdentifier(
String name
) {
appendLeadingQuote();
sb.append(name);
appendTrailingQuote();
return this;
}
/**
* append table name
*
* @param name
* @return
*/
public ExpressionBuilder appendTableName(String name) {
appendLeadingQuote();
sb.append(name);
appendTrailingQuote();
return this;
}
/**
* append column name
*
* @param name
* @return
*/
public ExpressionBuilder appendColumnName(String name) {
appendLeadingQuote();
sb.append(name);
appendTrailingQuote();
return this;
}
/**
* Append to this builder's expression the specified identifier, surrounded by the leading and
* trailing quotes.
*
* @param name the name to be appended
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendIdentifierQuoted(String name) {
appendLeadingQuote();
sb.append(name);
appendTrailingQuote();
return this;
}
/**
* Append to this builder's expression a new line.
*
* @return this builder to enable methods to be chained; never null
*/
public ExpressionBuilder appendNewLine() {
sb.append(System.lineSeparator());
return this;
}
public ExpressionBuilder append(Object obj) {
sb.append(obj);
return this;
}
public <T> ExpressionBuilder append(
T obj,
Transform<T> transform
) {
if (transform != null) {
transform.apply(this, obj);
} else {
append(obj);
}
return this;
}
public ListBuilder<Object> appendList() {
return new BasicListBuilder<>();
}
public ExpressionBuilder appendMultiple(String delimiter, String expression, int times) {
for (int i = 0; i < times; i++) {
if (i > 0) {
append(delimiter);
}
append(expression);
}
return this;
}
@Override
public String toString() {
return sb.toString();
}
/**
* A functional interface for a transformation that an expression builder might use when
* appending one or more other objects.
*
* @param <T> the type of object to transform before appending.
*/
@FunctionalInterface
public interface Transform<T> {
void apply(ExpressionBuilder builder, T input);
}
public interface ListBuilder<T> {
ListBuilder<T> delimitedBy(String delimiter);
<R> ListBuilder<R> transformedBy(Transform<R> transform);
ExpressionBuilder of(Iterable<? extends T> objects);
}
protected class BasicListBuilder<T> implements ListBuilder<T> {
private final String delimiter;
private final Transform<T> transform;
private boolean first = true;
BasicListBuilder() {
this(", ", null);
}
BasicListBuilder(String delimiter, Transform<T> transform) {
this.delimiter = delimiter;
this.transform = transform != null ? transform : ExpressionBuilder::append;
}
@Override
public ListBuilder<T> delimitedBy(String delimiter) {
return new BasicListBuilder<T>(delimiter, transform);
}
@Override
public <R> ListBuilder<R> transformedBy(Transform<R> transform) {
return new BasicListBuilder<>(delimiter, transform);
}
@Override
public ExpressionBuilder of(Iterable<? extends T> objects) {
for (T obj : objects) {
if (first) {
first = false;
} else {
append(delimiter);
}
append(obj, transform);
}
return ExpressionBuilder.this;
}
}
}