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

com.gs.fw.common.mithra.finder.WhereClause Maven / Gradle / Ivy

There is a newer version: 18.1.0
Show newest version
/*
 Copyright 2016 Goldman Sachs.
 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.gs.fw.common.mithra.finder;

import com.gs.collections.impl.list.mutable.FastList;
import com.gs.collections.impl.set.mutable.UnifiedSet;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.BitSet;
import java.util.List;
import java.util.Set;


public class WhereClause
{
    // why is StringBuilder final? This class would extend StringBuilder instead of being a bunch of static junk

    private static final char BRACKET_REPLACEMENT_CHAR = '\r';
    private static final char AND_REPLACEMENT_CHAR = '\n';
    private static final char OR_REPLACEMENT_CHAR = '\t';
    private static final String AND_REPLACEMENT_STRING = "\n\n\n\n";
    private static final String OR_REPLACEMENT_STRING = "\t\t\t\t";

    private StringBuilder whereClause = new StringBuilder(16);
    private List sqlParameterSetters = null;
    private WhereClauseOwner owner;
    private int orCount;
    private List tempTableJoins;
    private Set reachableColumns;
    private BooleanStack booleanStack; // true means boolean operation was added to the where clause

    public WhereClause(WhereClauseOwner owner)
    {
        this.owner = owner;
    }

    public int setSqlParameters(SqlQuery query, PreparedStatement ps, int count, WhereClauseOwner source) throws SQLException
    {
        if (source == this.owner && sqlParameterSetters != null)
        {
            for (int i = 0; i < sqlParameterSetters.size(); i++)
            {
                SqlParameterSetter sps = sqlParameterSetters.get(i);
                count += sps.setSqlParameters(ps, count, query);
            }
        }
        return count;
    }

    public boolean isInOrClause()
    {
        return orCount > 0;
    }

    public void clear()
    {
        this.whereClause.setLength(0);
        if (this.sqlParameterSetters != null)
        {
            this.sqlParameterSetters.clear();
        }
        if (tempTableJoins != null)
        {
            tempTableJoins.clear();
        }
        if (this.reachableColumns != null)
        {
            this.reachableColumns.clear();
        }
    }

    public int length()
    {
        return whereClause.length();
    }

    public WhereClause insert(int offset, String str)
    {
        checkOffsetToFill(offset);
        if (offset == whereClause.length())
        {
            whereClause.append(str);
        }
        else
        {
            whereClause.insert(offset, str);
        }
        return this;
    }

    private void checkOffsetToFill(int offset)
    {
        int start = offset - 1;
        if (start < 0) return;
        for(int i=start; i >= 0; i--)
        {
            switch (this.whereClause.charAt(i))
            {
                case BRACKET_REPLACEMENT_CHAR:
                    whereClause.setCharAt(i   , '(');
                    break;
                case AND_REPLACEMENT_CHAR:
                    whereClause.setCharAt(i-3 , ' ');
                    whereClause.setCharAt(i-2 , 'a');
                    whereClause.setCharAt(i-1 , 'n');
                    whereClause.setCharAt(i   , 'd');
                    return;
                case OR_REPLACEMENT_CHAR:
                    whereClause.setCharAt(i-3 , ' ');
                    whereClause.setCharAt(i-2 , 'o');
                    whereClause.setCharAt(i-1 , 'r');
                    whereClause.setCharAt(i   , ' ');
                    return;
                default:
                    return;
            }
        }
    }

    public WhereClause insert(int offset, CharSequence s)
    {
        checkOffsetToFill(offset);
        if (offset == whereClause.length())
        {
            whereClause.append(s);
        }
        else
        {
            whereClause.insert(offset, s);
        }
        return this;
    }

    public WhereClause insert(int offset, char c)
    {
        checkOffsetToFill(offset);
        if (offset == whereClause.length())
        {
            whereClause.append(c);
        }
        else
        {
            whereClause.insert(offset, c);
        }
        return this;
    }

    public WhereClause append(String str)
    {
        checkOffsetToFill(whereClause.length());
        whereClause.append(str);
        return this;
    }

    public WhereClause append(CharSequence s)
    {
        checkOffsetToFill(whereClause.length());
        whereClause.append(s);
        return this;
    }

    public WhereClause append(char c)
    {
        checkOffsetToFill(whereClause.length());
        whereClause.append(c);
        return this;
    }

    public WhereClause append(int i)
    {
        checkOffsetToFill(whereClause.length());
        whereClause.append(i);
        return this;
    }

    private boolean isBlank(int start, int end)
    {
        for(int i=start;i 1 && this.whereClause.subSequence(start-4, start).equals("and "))
        {
            start -= 4;
            if (this.whereClause.charAt(start - 1) == ' ')
            {
                start--;
                andLength++;
            }
        }
        else
        {
            // 3) and after this text
            if (this.whereClause.charAt(start +length + 4) == ' ')
            {
                andLength++;
            }
        }
        this.whereClause.delete(start, start + length + andLength);
        return -(length + andLength);
    }

    public void addReachableColumn(String fullyQualifiedColumn)
    {
        if (this.reachableColumns == null)
        {
            this.reachableColumns = UnifiedSet.newSet(4);
        }
        this.reachableColumns.add(fullyQualifiedColumn);
    }

    public boolean isColumnReachable(String fullyQualifiedColumnName)
    {
        return this.reachableColumns != null && this.reachableColumns.contains(fullyQualifiedColumnName);
    }

    private static class BooleanStack
    {
        private int size;
        private BitSet set = new BitSet();

        public void push(boolean val)
        {
            if (val)
            {
                set.set(size);
            }
            else
            {
                set.clear(size);
            }
            size++;
        }

        public boolean pop()
        {
            size--;
            return set.get(size);
        }

        public boolean peek()
        {
            return set.get(size - 1);
        }
    }

    public interface WhereClauseOwner
    {
        public WhereClause getWhereClause();

        public WhereClause getParentWhereClause(SqlQuery sqlQuery);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy