All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.blazebit.persistence.impl.function.groupconcat.AbstractGroupConcatFunction Maven / Gradle / Ivy
/*
* Copyright 2014 - 2020 Blazebit.
*
* 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.blazebit.persistence.impl.function.groupconcat;
import com.blazebit.persistence.impl.function.Order;
import com.blazebit.persistence.spi.FunctionRenderContext;
import com.blazebit.persistence.spi.JpqlFunction;
import com.blazebit.persistence.spi.TemplateRenderer;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Christian Beikov
* @since 1.0.0
*/
public abstract class AbstractGroupConcatFunction implements JpqlFunction {
public static final String FUNCTION_NAME = "group_concat";
protected final TemplateRenderer renderer;
public AbstractGroupConcatFunction(String template) {
this.renderer = new TemplateRenderer(template);
}
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
@Override
public Class getReturnType(Class firstArgumentType) {
return String.class;
}
@Override
public void render(FunctionRenderContext context) {
render(context, getGroupConcat(context));
}
public abstract void render(FunctionRenderContext context, GroupConcat groupConcat);
protected GroupConcat getGroupConcat(FunctionRenderContext context) {
if (context.getArgumentsSize() == 0) {
throw new RuntimeException("The group concat function needs at least one argument! args=" + context);
}
boolean distinct = false;
String expression;
int startIndex = 0;
int argsSize = context.getArgumentsSize();
String maybeDistinct = context.getArgument(0);
if ("'DISTINCT'".equalsIgnoreCase(maybeDistinct)) {
distinct = true;
startIndex++;
}
if (startIndex >= argsSize) {
throw new RuntimeException("The group concat function needs at least one expression to concatenate! args=" + context);
}
expression = context.getArgument(startIndex);
String separator = null;
String orderExpression = null;
List orders = new ArrayList();
Mode mode = null;
for (int i = startIndex + 1; i < argsSize; i++) {
String argument = context.getArgument(i);
if ("'SEPARATOR'".equalsIgnoreCase(argument)) {
mode = Mode.SEPARATOR;
} else if ("'ORDER BY'".equalsIgnoreCase(argument)) {
mode = Mode.ORDER_BY;
} else {
if (mode == Mode.ORDER_BY) {
Order order = getOrder(argument, orderExpression);
if (order != null) {
orders.add(order);
orderExpression = null;
} else {
if (orderExpression != null) {
orders.add(new Order(orderExpression, null, null));
}
orderExpression = argument;
}
} else if (mode == Mode.SEPARATOR) {
if (separator != null) {
throw new IllegalArgumentException("Illegal multiple separators for group concat '" + argument + "'. Expected 'ORDER BY'!");
}
separator = argument.substring(argument.indexOf('\'') + 1, argument.lastIndexOf('\''));
} else {
throw new IllegalArgumentException("Illegal input for group concat '" + argument + "'. Expected 'SEPARATOR' or 'ORDER BY'!");
}
}
}
if (orderExpression != null) {
orders.add(new Order(orderExpression, null, null));
}
if (separator == null) {
separator = ",";
}
return new GroupConcat(distinct, expression, orders, separator);
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
private enum Mode {
SEPARATOR,
ORDER_BY
}
protected void render(StringBuilder sb, Order order) {
sb.append(order.getExpression());
if (order.isAscending()) {
sb.append(" ASC");
} else {
sb.append(" DESC");
}
if (order.isNullsFirst()) {
sb.append(" NULLS FIRST");
} else {
sb.append(" NULLS LAST");
}
}
protected void appendEmulatedOrderByElementWithNulls(StringBuilder sb, Order element) {
sb.append("case when ");
sb.append(element.getExpression());
sb.append(" is null then ");
sb.append(element.isNullsFirst() ? 0 : 1);
sb.append(" else ");
sb.append(element.isNullsFirst() ? 1 : 0);
sb.append(" end, ");
sb.append(element.getExpression());
sb.append(element.isAscending() ? " asc" : " desc");
}
private static Order getOrder(String s, String expression) {
if (expression == null) {
return null;
}
String type = s.trim().toUpperCase();
if ("'ASC'".equals(type)) {
return new Order(expression, true, null);
} else if ("'DESC'".equals(type)) {
return new Order(expression, false, null);
} else if ("'ASC NULLS FIRST'".equals(type)) {
return new Order(expression, true, true);
} else if ("'ASC NULLS LAST'".equals(type)) {
return new Order(expression, true, false);
} else if ("'DESC NULLS FIRST'".equals(type)) {
return new Order(expression, false, true);
} else if ("'DESC NULLS LAST'".equals(type)) {
return new Order(expression, false, false);
}
return null;
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
public static final class GroupConcat {
private final boolean distinct;
private final String expression;
private final List orderBys;
private final String separator;
public GroupConcat(boolean distinct, String expression, List orderBys, String separator) {
this.distinct = distinct;
this.expression = expression;
this.orderBys = orderBys;
this.separator = separator;
}
public boolean isDistinct() {
return distinct;
}
public String getExpression() {
return expression;
}
public List getOrderBys() {
return orderBys;
}
public String getSeparator() {
return separator;
}
}
}