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

org.dbflute.cbean.chelper.HpSDRFunction Maven / Gradle / Ivy

There is a newer version: 1.2.8
Show newest version
/*
 * Copyright 2014-2019 the original author or authors.
 *
 * 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.dbflute.cbean.chelper;

import org.dbflute.cbean.ConditionBean;
import org.dbflute.cbean.ConditionQuery;
import org.dbflute.cbean.coption.DerivedReferrerOption;
import org.dbflute.cbean.coption.DerivedReferrerOptionFactory;
import org.dbflute.cbean.coption.FunctionFilterOptionCall;
import org.dbflute.cbean.exception.ConditionBeanExceptionThrower;
import org.dbflute.cbean.scoping.SubQuery;
import org.dbflute.dbmeta.DBMeta;
import org.dbflute.dbmeta.DBMetaProvider;
import org.dbflute.dbmeta.accessory.DerivedMappable;
import org.dbflute.dbmeta.info.ColumnInfo;
import org.dbflute.exception.IllegalConditionBeanOperationException;
import org.dbflute.exception.SpecifyDerivedReferrerInvalidAliasNameException;
import org.dbflute.util.Srl;

/**
 * The function for (Specify)DerivedReferrer.
 * @param  The type of referrer condition-bean.
 * @param  The type of local condition-query.
 * @author jflute
 */
public class HpSDRFunction {

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    protected final ConditionBean _baseCB;
    protected final LOCAL_CQ _localCQ;
    protected final HpSDRSetupper _querySetupper;
    protected final DBMetaProvider _dbmetaProvider;
    protected final DerivedReferrerOptionFactory _sdrOpFactory;

    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
    public HpSDRFunction(ConditionBean baseCB, LOCAL_CQ localCQ, HpSDRSetupper querySetupper,
            DBMetaProvider dbmetaProvider, DerivedReferrerOptionFactory sdrOpFactory) {
        _baseCB = baseCB;
        _localCQ = localCQ;
        _querySetupper = querySetupper;
        _dbmetaProvider = dbmetaProvider;
        _sdrOpFactory = sdrOpFactory;
    }

    // ===================================================================================
    //                                                                            Function
    //                                                                            ========
    // -----------------------------------------------------
    //                                                 Count
    //                                                 -----
    /**
     * Set up the sub query of referrer for the scalar 'count'.
     * 
     * cb.specify().derivePurchaseList().count(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseId(); // basically PK to count records
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchaseCount);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void count(SubQuery derivedCBLambda, String aliasName) { doCount(derivedCBLambda, aliasName, null); } /** * An overload method for count() with an option. So refer to the method's java-doc about basic info. *
     * cb.specify().derivePurchaseList().count(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseId(); // basically PK to count records
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchaseCount, op -> op.coalesce(0));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void count(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doCount(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doCount(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup("count", subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // Count Distinct // -------------- /** * Set up the sub query of referrer for the scalar 'count-distinct'. *
     * cb.specify().derivePurchaseList().countDistinct(purchaseCB -> {
     *     purchaseCB.specify().columnProductId(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_productKindCount);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void countDistinct(SubQuery derivedCBLambda, String aliasName) { doCountDistinct(derivedCBLambda, aliasName, null); } /** * An overload method for count() with an option. So refer to the method's java-doc about basic info. *
     * cb.specify().derivePurchaseList().countDistinct(purchaseCB -> {
     *     purchaseCB.specify().columnProductId(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_productKindCount, op -> op.coalesce(0));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void countDistinct(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doCountDistinct(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doCountDistinct(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup("count(distinct", subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // Max // ----- /** * Set up the sub query of referrer for the scalar 'max'. *
     * cb.specify().derivePurchaseList().max(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseDatetime(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_latestPurchaseDatetime);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void max(SubQuery derivedCBLambda, String aliasName) { doMax(derivedCBLambda, aliasName, null); } /** * An overload method for max() with an option. So refer to the method's java-doc. *
     * cb.specify().derivePurchaseList().max(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseDatetime(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_latestPurchaseDatetime, op -> op.coalesce("2011-06-07"));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void max(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doMax(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doMax(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup("max", subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // Min // ----- /** * Set up the sub query of referrer for the scalar 'min'. *
     * cb.specify().derivePurchaseList().min(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseDatetime(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_firstPurchaseDatetime);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void min(SubQuery derivedCBLambda, String aliasName) { doMin(derivedCBLambda, aliasName, null); } /** * An overload method for min() with an option. So refer to the method's java-doc. *
     * cb.specify().derivePurchaseList().min(purchaseCB -> {
     *     purchaseCB.specify().columnPurchaseDatetime(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_firstPurchaseDatetime, op -> op.coalesce("2011-06-07"));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void min(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doMin(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doMin(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup("min", subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // Sum // ----- /** * Set up the sub query of referrer for the scalar 'sum'. *
     * cb.specify().derivePurchaseList().sum(purchaseCB -> {
     *     purchaseCB.specify().columnPurchasePrice(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchasePriceSummary);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void sum(SubQuery derivedCBLambda, String aliasName) { doSum(derivedCBLambda, aliasName, null); } /** * An overload method for sum() with an option. So refer to the method's java-doc. *
     * cb.specify().derivePurchaseList().sum(purchaseCB -> {
     *     purchaseCB.specify().columnPurchasePrice(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchasePriceSummary, op -> op.coalesce(0));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void sum(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doSum(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doSum(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup("sum", subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // Average // ------- /** * Set up the sub query of referrer for the scalar 'avg'. *
     * cb.specify().derivePurchaseList().avg(purchaseCB -> {
     *     purchaseCB.specify().columnPurchasePrice(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchasePriceAverage);
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) */ public void avg(SubQuery derivedCBLambda, String aliasName) { doAvg(derivedCBLambda, aliasName, null); } /** * An overload method for avg() with an option. So refer to the method's java-doc. *
     * cb.specify().derivePurchaseList().avg(purchaseCB -> {
     *     purchaseCB.specify().columnPurchasePrice(); // derived column by function
     *     purchaseCB.query().setPaymentCompleteFlg_Equal_True(); // referrer condition
     * }, Member.ALIAS_purchasePriceAverage, op -> op.coalesce(0));
     * 
* @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ public void avg(SubQuery derivedCBLambda, String aliasName, FunctionFilterOptionCall opLambda) { doAvg(derivedCBLambda, aliasName, createDerivedReferrerOption(opLambda)); } protected void doAvg(SubQuery subQuery, String aliasName, DerivedReferrerOption option) { doSetupQuery("avg", subQuery, aliasName, option); } protected void doSetupQuery(String function, SubQuery subQuery, String aliasName, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); _querySetupper.setup(function, subQuery, _localCQ, filterAliasName(aliasName), option); } // ----------------------------------------------------- // User Definition // --------------- /** * Basically for database dependency (DBMS sub-class). {Internal}
* Not public because of condition-bean policy: cannot input SQL string. * @param derivedCBLambda The callback for sub-query of referrer. (NotNull) * @param aliasName The alias of the name. The property should exists on the entity. (NotNull) * @param function The function expression e.g. sum, max (NotNull) * @param opLambda The callback for option of DerivedReferrer. e.g. you can use a coalesce function. (NotNull) */ protected void userDef(SubQuery derivedCBLambda, String aliasName, String function, FunctionFilterOptionCall opLambda) { // closet doUserDef(derivedCBLambda, aliasName, function, createDerivedReferrerOption(opLambda)); } protected void doUserDef(SubQuery subQuery, String aliasName, String function, DerivedReferrerOption option) { assertSubQuery(subQuery); assertAliasName(aliasName); assertUserDefFunction(aliasName, function); _querySetupper.setup(function, subQuery, _localCQ, filterAliasName(aliasName), option); } // =================================================================================== // Assist Helper // ============= protected DerivedReferrerOption createDerivedReferrerOption(FunctionFilterOptionCall opLambda) { assertDerivedReferrerOption(opLambda); final DerivedReferrerOption option = newDerivedReferrerOption(); opLambda.callback(option); return option; } protected DerivedReferrerOption newDerivedReferrerOption() { return _sdrOpFactory.create(); } protected void assertSubQuery(SubQuery subQuery) { if (subQuery == null) { String msg = "The argument 'subQuery' for DerivedReferrer should not be null."; throw new IllegalArgumentException(msg); } } protected void assertAliasName(String aliasName) { doAssertInvalidAliasName(aliasName); doAssertConflictAliasName(aliasName); // *this check was moved to runtime (when creating a behavior command) //String tableDbName = _baseCB.asTableDbName(); //DBMeta dbmeta = _dbmetaProvider.provideDBMetaChecked(tableDbName); //Method[] methods = dbmeta.getEntityType().getMethods(); //String targetMethodName = "set" + replaceString(aliasName, "_", "").toLowerCase(); //boolean existsSetterMethod = false; //for (Method method : methods) { // if (!method.getName().startsWith("set")) { // continue; // } // if (targetMethodName.equals(method.getName().toLowerCase())) { // existsSetterMethod = true; // break; // } //} //if (!existsSetterMethod) { // throwSpecifyDerivedReferrerEntityPropertyNotFoundException(aliasName, dbmeta.getEntityType()); //} } protected void doAssertInvalidAliasName(String aliasName) { if (isPurposeNullAlias()) { if (aliasName != null) { String msg = "The aliasName should be null in the purpose: " + _baseCB.getPurpose(); throw new SpecifyDerivedReferrerInvalidAliasNameException(msg); } } else { // normal if (Srl.is_Null_or_TrimmedEmpty(aliasName)) { throwSpecifyDerivedReferrerInvalidAliasNameException(); } } } protected boolean isPurposeNullAlias() { final HpCBPurpose purpose = _baseCB.getPurpose(); return purpose.equals(HpCBPurpose.COLUMN_QUERY) || purpose.equals(HpCBPurpose.SCALAR_SELECT) || purpose.equals(HpCBPurpose.DERIVED_REFERRER); } protected void throwSpecifyDerivedReferrerInvalidAliasNameException() { createCBExThrower().throwSpecifyDerivedReferrerInvalidAliasNameException(_localCQ); } protected void doAssertConflictAliasName(String aliasName) { if (isPurposeNullAlias()) { return; } final String mappingAliasPrefix = DerivedMappable.MAPPING_ALIAS_PREFIX; final String realName; if (aliasName.startsWith(mappingAliasPrefix)) { realName = Srl.substringFirstRear(aliasName, mappingAliasPrefix); } else { realName = aliasName; } final String tableDbName = _baseCB.asTableDbName(); final DBMeta dbmeta = _dbmetaProvider.provideDBMetaChecked(tableDbName); if (dbmeta.hasColumn(realName)) { throwSpecifyDerivedReferrerConflictAliasNameException(aliasName, dbmeta.findColumnInfo(realName)); } } protected void throwSpecifyDerivedReferrerConflictAliasNameException(String aliasName, ColumnInfo existingColumn) { createCBExThrower().throwSpecifyDerivedReferrerConflictAliasNameException(_localCQ, aliasName, existingColumn); } // *this check was moved to runtime (when creating a behavior command) //protected void throwSpecifyDerivedReferrerEntityPropertyNotFoundException(String aliasName, Class entityType) { // createCBExThrower().throwSpecifyDerivedReferrerEntityPropertyNotFoundException(aliasName, entityType); //} //protected String replaceString(String text, String fromText, String toText) { // return Srl.replace(text, fromText, toText); //} protected void assertDerivedReferrerOption(FunctionFilterOptionCall opLambda) { if (opLambda == null) { String msg = "The argument 'opLambda' for DerivedReferrer should not be null."; throw new IllegalArgumentException(msg); } } protected String filterAliasName(String aliasName) { if (aliasName != null) { return aliasName.trim(); } else { final HpCBPurpose purpose = _baseCB.getPurpose(); if (isPurposeNullAlias()) { if (purpose.equals(HpCBPurpose.SCALAR_SELECT)) { return _baseCB.getSqlClause().getScalarSelectColumnAlias(); } else if (purpose.equals(HpCBPurpose.DERIVED_REFERRER)) { return _baseCB.getSqlClause().getDerivedReferrerNestedAlias(); } else { // for example, ColumnQuery return null; } } else { // basically no way because of checked before return null; } } } protected void assertUserDefFunction(String aliasName, String function) { if (!Srl.isAlphabetNumberHarfAllOr(function, '_')) { // e.g. ')', ';' are NG String msg = "Illegal function, only alphabet or number can be allowed:"; msg = msg + " aliasName=" + aliasName + ", function=" + function; throw new IllegalConditionBeanOperationException(msg); } } // =================================================================================== // Exception Helper // ================ protected ConditionBeanExceptionThrower createCBExThrower() { return new ConditionBeanExceptionThrower(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy