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

org.voltdb.parser.SQLPatternPartElement Maven / Gradle / Ivy

There is a newer version: 13.3.2-preview1
Show newest version
/* This file is part of VoltDB.
 * Copyright (C) 2008-2017 VoltDB Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with VoltDB.  If not, see .
 */

package org.voltdb.parser;

import java.util.regex.Pattern;

import org.voltcore.logging.VoltLogger;

public class SQLPatternPartElement extends SQLPatternPart
{
    //===== Private

    String m_leader = null;
    String m_trailer = null;
    String m_separator = null;
    private SQLPatternPart[] m_parts;
    String m_captureLabel = null;

    private static final VoltLogger COMPILER_LOG = new VoltLogger("COMPILER");

    /**
     * Private constructor from multiple strings
     * SQLPat static factory methods should be used for element creation.
     * @param strs  strings used for main part of expression
     */
    SQLPatternPartElement(String[] strs)
    {
        m_parts = new SQLPatternPart[strs.length];
        for (int i = 0; i < strs.length; ++i) {
            m_parts[i] = new SQLPatternPartString(strs[i]);
        }
    }

    /**
     * Private constructor from multiple elements
     * SQLPat static factory methods should be used for element creation.
     * @param parts  pattern parts
     */
    SQLPatternPartElement(SQLPatternPart... parts)
    {
        m_parts = parts;
    }

    /**
     * Private constructor from a single string
     * SQLPat static factory methods should be used for element creation.
     * @param strs  string used for main part of expression
     */
    SQLPatternPartElement(String str)
    {
        m_parts = new SQLPatternPart[] {new SQLPatternPartString(str)};
    }

    //===== Part interface

    @Override
    public String generateExpression(int flagsAdd)
    {
        int flags = m_flags | flagsAdd;
        StringBuilder sb = new StringBuilder();
        if (m_leader != null) {
            sb.append(m_leader);
        }
        // Need a non-capturing group when either an explicit non-capturing group is
        // requested or it is optional. The only case where a non-capturing group isn't
        // needed for an optional is an explicit capture without leading space.
        boolean captureGroup = (flags & SQLPatternFactory.CAPTURE) != 0;
        boolean explicitNonCaptureGroup = !captureGroup && (flags & SQLPatternFactory.GROUP) != 0;
        boolean optional = ((flags & SQLPatternFactory.OPTIONAL) != 0);
        // Suppress the leading space at this level when it should be pushed down to the child.
        boolean leadingSpace = ((flags & SQLPatternFactory.LEADING_SPACE) != 0);
        boolean leadingSpaceToChild = ((flags & SQLPatternFactory.ADD_LEADING_SPACE_TO_CHILD) != 0);
        boolean childLeadingSpace = ((flags & SQLPatternFactory.CHILD_SPACE_SEPARATOR) != 0 ||
                                     (leadingSpace && leadingSpaceToChild));
        boolean nonCaptureGroup = (explicitNonCaptureGroup ||
                                  (optional && (!captureGroup || leadingSpace)));
        boolean innerOptional = optional && captureGroup && !nonCaptureGroup;
        boolean outerOptional = optional && nonCaptureGroup;
        if (nonCaptureGroup) {
            sb.append("(?:");
        }
        if (leadingSpace && !leadingSpaceToChild) {
            // Protect something like an OR sequence by using an inner group
            sb.append("\\s+(?:");
        }
        if (captureGroup) {
            if (m_captureLabel != null) {
                sb.append(String.format("(?<%s>", m_captureLabel));
            }
            else {
                sb.append("(");
            }
        }
        for (int i = 0; i < m_parts.length; ++i) {
            int flagsAddChild = 0;
            if (i > 0) {
                if (m_separator != null) {
                    sb.append(m_separator);
                }
                if (childLeadingSpace) {
                    flagsAddChild |= SQLPatternFactory.LEADING_SPACE;
                }
            }
            else if (childLeadingSpace && leadingSpaceToChild) {
                flagsAddChild |= SQLPatternFactory.LEADING_SPACE;
            }
            sb.append(m_parts[i].generateExpression(flagsAddChild));
        }
        if (captureGroup) {
            sb.append(")");
        }
        if (innerOptional) {
            sb.append("?");
        }
        if (leadingSpace && !leadingSpaceToChild) {
            sb.append(")");
        }
        if (nonCaptureGroup) {
            sb.append(")");
        }
        if (outerOptional) {
            sb.append("?");
        }
        if (m_trailer != null) {
            sb.append(m_trailer);
        }
        return sb.toString();
    }

    @Override
    public void setCaptureLabel(String captureLabel)
    {
        m_captureLabel = captureLabel;
    }

    @Override
    public Pattern compile(String label)
    {
        int reFlags = 0;
        if ((m_flags & SQLPatternFactory.CASE_SENSITIVE) == 0) {
            reFlags |= Pattern.CASE_INSENSITIVE;
        }
        if ((m_flags & SQLPatternFactory.IGNORE_NEW_LINE) == 0) {
            reFlags |= Pattern.DOTALL;
        }
        if ((m_flags & SQLPatternFactory.SINGLE_LINE) == 0) {
            reFlags |= Pattern.MULTILINE;
        }
        String regex = generateExpression(0);
        COMPILER_LOG.debug(String.format("PATTERN: %s: %s", label, regex));
        return Pattern.compile(regex, reFlags);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy