All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jn.sqlhelper.dialect.orderby.SymbolStyleOrderByBuilder Maven / Gradle / Ivy

/*
 * Copyright 2019 the original author or authors.
 *
 * Licensed under the LGPL, Version 3.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.gnu.org/licenses/lgpl-3.0.html
 *
 * 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.jn.sqlhelper.dialect.orderby;

import com.jn.langx.annotation.NonNull;
import com.jn.langx.util.Strings;
import com.jn.sqlhelper.common.symbolmapper.SqlSymbolMapper;
import com.jn.sqlhelper.common.symbolmapper.NoopSymbolMapper;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * 1) +expression1, -expression2
 * 2) expression1+, expression2-
 */
public class SymbolStyleOrderByBuilder implements OrderByBuilder {
    private String ascSymbol;
    private String descSymbol;

    private Map symbolMap = new HashMap();
    private SqlSymbolMapper sqlSymbolMapper = NoopSymbolMapper.DEFAULT;

    public static final SymbolStyleOrderByBuilder MATH_SYMBOL_ORDER_BY_BUILDER = new SymbolStyleOrderByBuilder("+", "-");

    public SymbolStyleOrderByBuilder() {
    }

    public SymbolStyleOrderByBuilder(String ascSymbol, String descSymbol) {
        ascSymbol(ascSymbol);
        descSymbol(descSymbol);
    }

    public SymbolStyleOrderByBuilder sqlSymbolMapper(SqlSymbolMapper sqlSymbolMapper) {
        if (sqlSymbolMapper != null) {
            this.sqlSymbolMapper = sqlSymbolMapper;
        }
        return this;
    }

    @Override
    public OrderBy build(String s) {
        if (Strings.isBlank(ascSymbol) || Strings.isBlank(descSymbol)) {
            throw new OrderBySymbolException("OrderByBuilder symbol is illegal, ascSymbol:" + ascSymbol + ",descSymbol:" + descSymbol);
        }

        if (Strings.isBlank(s)) {
            return OrderBy.EMPTY;
        }

        OrderBy orderBy = new OrderBy();
        String currentSymbol = null;
        String currentExpression = null;

        StringTokenizer tokenizer = new StringTokenizer(s, " \t\n\r\f,", true);
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            if (Strings.isBlank(token)) {
                continue;
            }

            boolean isAscSymbol = ascSymbol.equals(token);
            boolean isDescSymbol = descSymbol.equals(token);
            boolean isDelimiter = ",".equals(token);

            if (isAscSymbol || isDescSymbol) {
                currentSymbol = token;
            } else if (!isDelimiter) {
                String lastOrderBySymbolForCurrentExpression = null;
                while (token.startsWith(ascSymbol) || token.startsWith(descSymbol)) {
                    if (token.startsWith(ascSymbol)) {
                        token = token.substring(ascSymbol.length());
                        lastOrderBySymbolForCurrentExpression = ascSymbol;
                    } else {
                        token = token.substring(descSymbol.length());
                        lastOrderBySymbolForCurrentExpression = descSymbol;
                    }
                }
                while (token.endsWith(ascSymbol) || token.endsWith(descSymbol)) {
                    if (token.endsWith(ascSymbol)) {
                        token = token.substring(0, token.lastIndexOf(ascSymbol));
                        lastOrderBySymbolForCurrentExpression = ascSymbol;
                    } else {
                        token = token.substring(0, token.lastIndexOf(descSymbol));
                        lastOrderBySymbolForCurrentExpression = descSymbol;
                    }
                }
                if (lastOrderBySymbolForCurrentExpression != null) {
                    currentSymbol = lastOrderBySymbolForCurrentExpression;
                }
                currentExpression = token;
            } else {
                if (currentExpression != null) {
                    orderBy.add(new OrderByItem(sqlSymbolMapper.apply(currentExpression), OrderByType.fromString(symbolMap.get(currentSymbol))));
                }
                currentExpression = null;
                currentSymbol = null;
            }
        }
        if (currentExpression != null) {
            orderBy.add(new OrderByItem(sqlSymbolMapper.apply(currentExpression), OrderByType.fromString(symbolMap.get(currentSymbol))));
        }
        return orderBy;
    }

    public String ascSymbol() {
        return ascSymbol;
    }

    public SymbolStyleOrderByBuilder ascSymbol(String ascSymbol) {
        if (isValidSymbol(ascSymbol)) {
            this.ascSymbol = ascSymbol;
            removeSymbolMapForValue("asc");
            symbolMap.put(ascSymbol, "asc");
        }
        return this;
    }


    public SymbolStyleOrderByBuilder descSymbol(String descSymbol) {
        if (isValidSymbol(descSymbol)) {
            this.descSymbol = descSymbol;
            removeSymbolMapForValue("desc");
            symbolMap.put(descSymbol, "desc");
        }
        return this;
    }


    private void removeSymbolMapForValue(@NonNull String value) {
        Iterator> iter = symbolMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = iter.next();
            if (value.equals(entry.getValue())) {
                iter.remove();
            }
        }
    }

    private boolean isValidSymbol(String symbol) {
        if (Strings.isBlank(symbol)) {
            return false;
        }
        symbol = symbol.trim();
        if ("?".equals(symbol)) {
            return false;
        }
        return true;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy