<commit_before>/* Copyright 2005 I Serv Consultoria Empresarial Ltda.
 *
 * 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 org.helianto.core.filter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * Build an EJB-QL string criteria, appropriate to be appended
 * after the "where" keyword in a query.
 * 
 * <p><code>CriteriaBuilder</code> supports nesting, i.e., a
 * <code>CriteriaBuilder</code> instance can be built from 
 * one or more second-level instances.</p>
 * 
 * @author <NAME>
 */
public class CriteriaBuilder {

    static String DEFAULT_SQL_CONVERSION_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    static String DEFAULT_AND_CONNECTOR = "AND ";
    static String DEFAULT_OR_CONNECTOR = "OR ";

    private String prefix;
    private String connector = DEFAULT_AND_CONNECTOR;
    private StringBuilder criteria;
    private DateFormat formatter;
    private int openCount = 0;
    private int segmentCount = 0;

    /**
     * Default constructor.
     */
    public CriteriaBuilder(String prefix) {
        this(prefix, DEFAULT_SQL_CONVERSION_DATE_FORMAT);
    }
    
    /**
     * Constructor taking a date format string.
     */
    public CriteriaBuilder(String prefix, String dateFormat) {
        setDateFormat(dateFormat);
        createCriteria(prefix);
    }
    
    /**
     * Set the date format.
     * 
     * @param dateFormat
     */
    public void setDateFormat(String dateFormat) {
        formatter = new SimpleDateFormat(dateFormat);
    }

    /**
     * Initialize a criteria.
     * 
     * @param prefix
     */
    public void createCriteria(String prefix) {
        this.prefix = prefix;
        criteria = new StringBuilder();
    }

    /**
     * Append an <code>Entity</code> filter if a <code>User</code> is present, or throws 
     * <code>IllegalArgumentException</code>.
     * 
     * @param filter
     */
    public CriteriaBuilder appendEntityFromUserBackedFilter(UserBackedFilter filter) {
        if (filter.getUser()==null) {
            throw new IllegalArgumentException("User required!");
        }
        appendSegment("entity.id", "=")
        .append(filter.getUser().getEntity().getId());
        return this;
    }
    
    /**
     * Filed name appender that can suppress the initial connector.
     * 
     * @param fieldName
     * @param sqlOperator
     */
    public CriteriaBuilder appendSegment(String fieldName, String sqlOperator) {
        segmentCount++;
        criteria.append(prefix).append(".")
            .append(fieldName)
            .append(" ")
            .append(sqlOperator)
            .append(" ");
        return this;
    }
    
    /**
     * And appender.
     */
    public CriteriaBuilder appendAnd() {
        if (segmentCount>0) {
            criteria.append(DEFAULT_AND_CONNECTOR);
        }
        return this;
    }
    
    /**<commit_msg>added support to sql functions when building criteria segment<commit_after>/* Copyright 2005 I Serv Consultoria Empresarial Ltda.
 *
 * 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 org.helianto.core.filter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * Build an EJB-QL string criteria, appropriate to be appended
 * after the "where" keyword in a query.
 * 
 * <p><code>CriteriaBuilder</code> supports nesting, i.e., a
 * <code>CriteriaBuilder</code> instance can be built from 
 * one or more second-level instances.</p>
 * 
 * @author <NAME>
 */
public class CriteriaBuilder {

    static String DEFAULT_SQL_CONVERSION_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    static String DEFAULT_AND_CONNECTOR = "AND ";
    static String DEFAULT_OR_CONNECTOR = "OR ";

    private String prefix;
    private String connector = DEFAULT_AND_CONNECTOR;
    private StringBuilder criteria;
    private DateFormat formatter;
    private int openCount = 0;
    private int segmentCount = 0;

    /**
     * Default constructor.
     */
    public CriteriaBuilder(String prefix) {
        this(prefix, DEFAULT_SQL_CONVERSION_DATE_FORMAT);
    }
    
    /**
     * Constructor taking a date format string.
     */
    public CriteriaBuilder(String prefix, String dateFormat) {
        setDateFormat(dateFormat);
        createCriteria(prefix);
    }
    
    /**
     * Set the date format.
     * 
     * @param dateFormat
     */
    public void setDateFormat(String dateFormat) {
        formatter = new SimpleDateFormat(dateFormat);
    }

    /**
     * Initialize a criteria.
     * 
     * @param prefix
     */
    public void createCriteria(String prefix) {
        this.prefix = prefix;
        criteria = new StringBuilder();
    }

    /**
     * Append an <code>Entity</code> filter if a <code>User</code> is present, or throws 
     * <code>IllegalArgumentException</code>.
     * 
     * @param filter
     */
    public CriteriaBuilder appendEntityFromUserBackedFilter(UserBackedFilter filter) {
        if (filter.getUser()==null) {
            throw new IllegalArgumentException("User required!");
        }
        appendSegment("entity.id", "=")
        .append(filter.getUser().getEntity().getId());
        return this;
    }
    
    /**
     * Filed name appender that can suppress the initial connector.
     * 
     * @param fieldName
     * @param sqlOperator
     */
    public CriteriaBuilder appendSegment(String fieldName, String sqlOperator) {
        return appendSegment(fieldName, sqlOperator, "");
    }
    
    /**
     * Filed name appender that can suppress the initial connector.
     * 
     * @param fieldName
     * @param sqlOperator
     * @param sqlFunction
     */
    public CriteriaBuilder appendSegment(String fieldName, String sqlOperator, String sqlFunction) {
        segmentCount++;
        if (!sqlFunction.equals("")) {
            criteria.append(sqlFunction).append("(");
        }
        criteria.append(prefix).append(".")
            .append(fieldName);
        if (!sqlFunction.equals("")) {
            criteria.append(sqlFunction).append(")");
        }
        criteria.append(" ")
            .append(sqlOperator)
            .append(" ");
        return this;
    }
    
    /**
     * And appender.
     */
    public CriteriaBuilder appendAnd() {
        if (segmentCount>0) {
            criteria.append(DEFAULT_AND_CONNECTOR);
        }
        return this;
    }
    
    /**
{'fraction_non_alphanumeric': 0.10020256583389602, 'fraction_numerical': 0.002970965563808238, 'mean_word_length': 2.536771728748806, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7061576', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1964, 'n_words': 594}