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

org.dbflute.cbean.ordering.ManualOrderOption Maven / Gradle / Ivy

/*
 * Copyright 2014-2020 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.ordering;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import org.dbflute.cbean.ConditionBean;
import org.dbflute.cbean.chelper.HpCalcSpecification;
import org.dbflute.cbean.chelper.HpManualOrderThemeListHandler;
import org.dbflute.cbean.chelper.HpMobCaseWhenElement;
import org.dbflute.cbean.chelper.HpMobConnectedBean;
import org.dbflute.cbean.chelper.HpMobConnectionMode;
import org.dbflute.cbean.ckey.ConditionKey;
import org.dbflute.cbean.coption.ColumnConversionOption;
import org.dbflute.cbean.coption.ConditionOptionCall;
import org.dbflute.cbean.coption.FromToOption;
import org.dbflute.cbean.coption.FunctionFilterOptionCall;
import org.dbflute.cbean.dream.ColumnCalculator;
import org.dbflute.cbean.dream.SpecifiedColumn;
import org.dbflute.cbean.scoping.SpecifyQuery;
import org.dbflute.dbmeta.info.ColumnInfo;
import org.dbflute.exception.IllegalConditionBeanOperationException;
import org.dbflute.helper.message.ExceptionMessageBuilder;
import org.dbflute.jdbc.Classification;
import org.dbflute.jdbc.ClassificationCodeType;
import org.dbflute.system.DBFluteSystem;
import org.dbflute.twowaysql.DisplaySqlBuilder;
import org.dbflute.util.DfTypeUtil;

/**
 * The option for manual order.
 * 
 * MemberCB cb = new MemberCB();
 * ManualOrderOption mob = new ManualOrderOption();
 * mob.when_GreaterEqual(priorityDate); // e.g. 2000/01/01
 * cb.query().addOrderBy_Birthdate_Asc().withManualOrder(mob);
 * // order by 
 * //   case
 * //     when BIRTHDATE >= '2000/01/01' then 0
 * //     else 1
 * //   end asc, ...
 *
 * MemberCB cb = new MemberCB();
 * ManualOrderOption mob = new ManualOrderOption();
 * mob.when_Equal(CDef.MemberStatus.Withdrawal);
 * mob.when_Equal(CDef.MemberStatus.Formalized);
 * mob.when_Equal(CDef.MemberStatus.Provisional);
 * cb.query().addOrderBy_MemberStatusCode_Asc().withManualOrder(mob);
 * // order by 
 * //   case
 * //     when MEMBER_STATUS_CODE = 'WDL' then 0
 * //     when MEMBER_STATUS_CODE = 'FML' then 1
 * //     when MEMBER_STATUS_CODE = 'PRV' then 2
 * //     else 3
 * //   end asc, ...
 * 
*

This function with Union is unsupported!

*

The order values are bound (treated as bind parameter).

* @author jflute * @since 0.9.8.2 (2011/04/08 Friday) */ public class ManualOrderOption implements ColumnCalculator { // =================================================================================== // Definition // ========== public static final String THEME_KEY = "ManualOrder"; // =================================================================================== // Attribute // ========= protected final List _caseWhenAcceptedList = new ArrayList(); protected final List _caseWhenBoundList = new ArrayList(); protected HpCalcSpecification _calcSpecification; protected HpMobConnectionMode _connectionMode; // null means no connection // basically for switch order protected Object _elseAcceptedValue; protected Object _elseBoundValue; // for DBMS that doesn't support binding there protected boolean _suppressThenBinding; protected boolean _suppressElseBinding; // =================================================================================== //   Case When // ========= // ----------------------------------------------------- // when_... // -------- /** * Add 'when' element for 'case' statement as Equal(=). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_Equal(Object orderValue) { return doWhen(ConditionKey.CK_EQUAL, orderValue); } /** * Add 'when' element for 'case' statement as NotEqual(<>). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_NotEqual(Object orderValue) { return doWhen(ConditionKey.CK_NOT_EQUAL_STANDARD, orderValue); } /** * Add 'when' element for 'case' statement as GreaterThan(>). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_GreaterThan(Object orderValue) { return doWhen(ConditionKey.CK_GREATER_THAN, orderValue); } /** * Add 'when' element for 'case' statement as LessThan(<). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_LessThan(Object orderValue) { return doWhen(ConditionKey.CK_LESS_THAN, orderValue); } /** * Add 'when' element for 'case' statement as GreaterEqual(>=). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_GreaterEqual(Object orderValue) { return doWhen(ConditionKey.CK_GREATER_EQUAL, orderValue); } /** * Add 'when' element for 'case' statement as LessEqual(<=). * @param orderValue The value for ordering. (NullAllowed: if null, means invalid condition) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_LessEqual(Object orderValue) { return doWhen(ConditionKey.CK_LESS_EQUAL, orderValue); } /** * Add 'when' element for 'case' statement as IsNull. * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_IsNull() { return doWhen(ConditionKey.CK_IS_NULL, null); } /** * Add 'when' element for 'case' statement as IsNotNull. * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_IsNotNull() { return doWhen(ConditionKey.CK_IS_NOT_NULL, null); } /** * Add 'when' element for 'case' statement as FromTo using local date.
* You can set various from-to patterns by the from-to option.
* compareAsDate(), compareAsMonth(), compareAsYear(), and so on...
* See the {@link FromToOption} class for the details. * @param fromDate The local date as from-date. (basically NotNull: null allowed if one-side allowed) * @param toDate The local date as to-date. (basically NotNull: null allowed if one-side allowed) * @param opLambda The callback for option of from-to. (NotNull) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_FromTo(LocalDate fromDate, LocalDate toDate, ConditionOptionCall opLambda) { // #date_parade return doWhen_FromTo(toDate(fromDate), toDate(toDate), createFromToOption(opLambda)); } /** * Add 'when' element for 'case' statement as FromTo using local date-time.
* You can set various from-to patterns by the from-to option.
* compareAsDate(), compareAsMonth(), compareAsYear(), and so on...
* See the {@link FromToOption} class for the details. * @param fromDate The local date-time as from-date. (basically NotNull: null allowed if one-side allowed) * @param toDate The local date-time as to-date. (basically NotNull: null allowed if one-side allowed) * @param opLambda The callback for option of from-to. (NotNull) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_FromTo(LocalDateTime fromDate, LocalDateTime toDate, ConditionOptionCall opLambda) { return doWhen_FromTo(toDate(fromDate), toDate(toDate), createFromToOption(opLambda)); } /** * Add 'when' element for 'case' statement as FromTo.
* You can set various from-to patterns by the from-to option.
* compareAsDate(), compareAsMonth(), compareAsYear(), and so on...
* See the {@link FromToOption} class for the details. * @param fromDate The date as from-date. (basically NotNull: null allowed if one-side allowed) * @param toDate The date as to-date. (basically NotNull: null allowed if one-side allowed) * @param opLambda The callback for option of from-to. (NotNull) * @return The bean for connected order, which you can set second or more conditions by. (NotNull) */ public HpMobConnectedBean when_FromTo(Date fromDate, Date toDate, ConditionOptionCall opLambda) { return doWhen_FromTo(fromDate, toDate, createFromToOption(opLambda)); } protected FromToOption createFromToOption(ConditionOptionCall opLambda) { assertFromToOptionCall(opLambda); final FromToOption op = newFromToOption(); opLambda.callback(op); return op; } protected void assertFromToOptionCall(ConditionOptionCall opLambda) { if (opLambda == null) { String msg = "The argument 'opLambda' for from-to option of ManualOrder should not be null."; throw new IllegalConditionBeanOperationException(msg); } } protected FromToOption newFromToOption() { return new FromToOption(); } protected HpMobConnectedBean doWhen_FromTo(Date fromDate, Date toDate, FromToOption option) { assertFromToOption(option); assertFromToDateBothExistsOrOneSideAllowed(fromDate, toDate, option); final ConditionKey fromDateConditionKey = option.getFromDateConditionKey(); final ConditionKey toDateConditionKey = option.getToDateConditionKey(); final Date filteredFromDate = option.filterFromDate(fromDate); final Date filteredToDate = option.filterToDate(toDate); return doWhen(fromDateConditionKey, filteredFromDate).doAnd(toDateConditionKey, filteredToDate); } protected void assertFromToOption(FromToOption option) { if (option == null) { String msg = "The argument 'option' for from-to should not be null."; throw new IllegalConditionBeanOperationException(msg); } } protected void assertFromToDateBothExistsOrOneSideAllowed(Date fromDate, Date toDate, FromToOption option) { final boolean oneSideAllowed = option.isOneSideAllowed(); if (fromDate == null && toDate == null) { String msg = "The both arguments of from-to for ManualOrder were null: " + option; throw new IllegalConditionBeanOperationException(msg); } else if (fromDate == null && !oneSideAllowed) { String msg = "The argument 'fromDate' of from-to for ManualOrder was null:"; msg = msg + " toDate=" + toDate + " option=" + option; throw new IllegalConditionBeanOperationException(msg); } else if (toDate == null && !oneSideAllowed) { String msg = "The argument 'toDate' of from-to for ManualOrder was null:"; msg = msg + " fromDate=" + fromDate + " option=" + option; throw new IllegalConditionBeanOperationException(msg); } } // ----------------------------------------------------- // Order Value // ----------- /** * Accept the list of order value as equal condition. *
     * List<CDef.MemberStatus> orderValueList = new ArrayList<CDef.MemberStatus>();
     * orderValueList.add(CDef.MemberStatus.Withdrawal);
     * orderValueList.add(CDef.MemberStatus.Formalized);
     * orderValueList.add(CDef.MemberStatus.Provisional);
     * cb.query().addOrderBy_MemberStatusCode_Asc().withManualOrder(op -> {
     *     op.acceptOrderValueList(orderValueList);
     * });
     * // order by 
     * //   case
     * //     when MEMBER_STATUS_CODE = 'WDL' then 0
     * //     when MEMBER_STATUS_CODE = 'FML' then 1
     * //     when MEMBER_STATUS_CODE = 'PRV' then 2
     * //     else 3
     * //   end asc, ...
     * 
* @param orderValueList The list of order value. (NotNull) */ public void acceptOrderValueList(List orderValueList) { if (orderValueList == null) { String msg = "The argument 'orderValueList' should not be null."; throw new IllegalArgumentException(msg); } for (Object orderValue : orderValueList) { when_Equal(orderValue); } } // ----------------------------------------------------- // Assist Helper // ------------- protected HpMobConnectedBean doWhen(ConditionKey conditionKey, Object orderValue) { if (orderValue == null && !isManualOrderConditionKeyNullHandling(conditionKey)) { String msg = "The argument 'orderValue' should not be null: conditionKey=" + conditionKey; throw new IllegalArgumentException(msg); } final HpMobCaseWhenElement addedElement = createElement(conditionKey, orderValue); if (_connectionMode != null) { if (_caseWhenAcceptedList.isEmpty()) { throwManualOrderPreviousConditionNotFoundException(_connectionMode, conditionKey, orderValue); } addedElement.setConnectionMode(_connectionMode); final HpMobCaseWhenElement lastElement = getAcceptedLastElement(); final List connectedElementList = lastElement.getConnectedElementList(); if (!connectedElementList.isEmpty()) { // check same connectors final HpMobCaseWhenElement previousConnected = connectedElementList.get(connectedElementList.size() - 1); final HpMobConnectionMode previousMode = previousConnected.getConnectionMode(); if (previousMode != null && !previousMode.equals(addedElement.getConnectionMode())) { throwManualOrderTwoConnectorUnsupportedException(conditionKey, orderValue, lastElement); } } lastElement.addConnectedElement(addedElement); } else { _caseWhenAcceptedList.add(addedElement); } return createConnectedBean(); } protected boolean isManualOrderConditionKeyNullHandling(ConditionKey conditionKey) { return conditionKey.equals(ConditionKey.CK_IS_NULL) || conditionKey.equals(ConditionKey.CK_IS_NOT_NULL); } protected HpMobCaseWhenElement getAcceptedLastElement() { return _caseWhenAcceptedList.get(_caseWhenAcceptedList.size() - 1); } protected HpMobConnectedBean createConnectedBean() { return new HpMobConnectedBean(this); } protected void throwManualOrderPreviousConditionNotFoundException(HpMobConnectionMode mode, ConditionKey conditionKey, Object orderValue) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Not found previous condition of 'case when' for connecting next condition."); br.addItem("Advice"); br.addElement("You should set first condition before setting next condition."); br.addItem("Connection Mode"); br.addElement(mode); br.addItem("Added ConnectionKey"); br.addElement(conditionKey); br.addItem("Added OrderValue"); br.addElement(orderValue); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } protected void throwManualOrderTwoConnectorUnsupportedException(ConditionKey conditionKey, Object orderValue, HpMobCaseWhenElement lastElement) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("both two connectors and/or were set."); br.addItem("Advice"); br.addElement("Unsupported using both two connectors and/or in one case."); br.addElement("For example:"); br.addElement(" (o): when FOO > 1 and FOO < 9 then ..."); br.addElement(" (o): when FOO >= 1 or FOO >= 9 then ..."); br.addElement(" (x): when FOO >= 1 and FOO >= 9 or FOO = 20 then ..."); br.addItem("Added ConditionKey"); br.addElement(conditionKey); br.addItem("Added OrderValue"); br.addElement(orderValue); br.addItem("Fixed ConnectionMode"); br.addElement(lastElement.getConnectionMode()); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } // =================================================================================== // Then/Else // ========= public void xregisterThenValueToLastElement(Object thenValue) { if (thenValue == null) { String msg = "The argument 'thenValue' should not be null."; throw new IllegalArgumentException(msg); } if (_caseWhenAcceptedList.isEmpty()) { throwManualOrderThenValueCaseWhenElementNotFoundException(thenValue); } final HpMobCaseWhenElement lastElement = getAcceptedLastElement(); lastElement.setThenValue(thenValue); } protected void throwManualOrderThenValueCaseWhenElementNotFoundException(Object thenValue) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Not found 'case when' element for 'then' value."); br.addItem("Advice"); br.addElement("You should set 'case when' element before setting 'then' value."); br.addItem("Added ThenValue"); br.addElement(thenValue); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } /** * Add 'else' value. (Basically for SwitchOrder)
* You should set 'then' values before calling this. * @param elseValue The value for 'else', String, Integer, Date, DreamCruiseTicket... (NotNull) */ public void elseEnd(Object elseValue) { // cannot be 'else()' for reservation word if (elseValue == null) { String msg = "The argument 'elseValue' should not be null."; throw new IllegalArgumentException(msg); } if (_caseWhenAcceptedList.isEmpty()) { throwManualOrderElseValueCaseWhenElementNotFoundException(elseValue); } _elseAcceptedValue = elseValue; } protected void throwManualOrderElseValueCaseWhenElementNotFoundException(Object elseValue) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Not found 'case when' element for 'else' value."); br.addItem("Advice"); br.addElement("You should set 'case when' element before setting 'else' value."); br.addElement("For example:"); br.addElement(" (x):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.elseEnd(0); // *NG"); br.addElement(" (o):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_Equal(...); // *Don't forget here"); br.addElement(" mob.elseEnd(0); // OK"); br.addItem("Added ThenValue"); br.addElement(elseValue); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } // =================================================================================== // Calculation // =========== /** * {@inheritDoc} */ public ColumnCalculator plus(Number plusValue) { assertObjectNotNull("plusValue", plusValue); initializeCalcSpecificationIfNeeds(); return _calcSpecification.plus(plusValue); } /** * {@inheritDoc} */ public ColumnCalculator plus(SpecifiedColumn plusColumn) { assertObjectNotNull("plusColumn", plusColumn); assertCalculationColumnNumber(plusColumn); assertSpecifiedDreamCruiseTicket(plusColumn); initializeCalcSpecificationIfNeeds(); return _calcSpecification.plus(plusColumn); } /** * {@inheritDoc} */ public ColumnCalculator minus(Number minusValue) { assertObjectNotNull("minusValue", minusValue); initializeCalcSpecificationIfNeeds(); return _calcSpecification.minus(minusValue); } /** * {@inheritDoc} */ public ColumnCalculator minus(SpecifiedColumn minusColumn) { assertObjectNotNull("minusColumn", minusColumn); assertCalculationColumnNumber(minusColumn); assertSpecifiedDreamCruiseTicket(minusColumn); initializeCalcSpecificationIfNeeds(); return _calcSpecification.minus(minusColumn); } /** * {@inheritDoc} */ public ColumnCalculator multiply(Number multiplyValue) { assertObjectNotNull("multiplyValue", multiplyValue); initializeCalcSpecificationIfNeeds(); return _calcSpecification.multiply(multiplyValue); } /** * {@inheritDoc} */ public ColumnCalculator multiply(SpecifiedColumn multiplyColumn) { assertObjectNotNull("multiplyColumn", multiplyColumn); assertCalculationColumnNumber(multiplyColumn); assertSpecifiedDreamCruiseTicket(multiplyColumn); initializeCalcSpecificationIfNeeds(); return _calcSpecification.multiply(multiplyColumn); } /** * {@inheritDoc} */ public ColumnCalculator divide(Number divideValue) { assertObjectNotNull("divideValue", divideValue); initializeCalcSpecificationIfNeeds(); return _calcSpecification.divide(divideValue); } /** * {@inheritDoc} */ public ColumnCalculator divide(SpecifiedColumn divideColumn) { assertObjectNotNull("divideColumn", divideColumn); assertCalculationColumnNumber(divideColumn); assertSpecifiedDreamCruiseTicket(divideColumn); initializeCalcSpecificationIfNeeds(); return _calcSpecification.divide(divideColumn); } /** * {@inheritDoc} */ public ColumnCalculator convert(FunctionFilterOptionCall opLambda) { assertObjectNotNull("opLambda", opLambda); initializeCalcSpecificationIfNeeds(); return _calcSpecification.convert(opLambda); } /** * {@inheritDoc} */ public ColumnCalculator left() { initializeCalcSpecificationIfNeeds(); return _calcSpecification.left(); } /** * {@inheritDoc} */ public ColumnCalculator right() { initializeCalcSpecificationIfNeeds(); return _calcSpecification.right(); } protected void initializeCalcSpecificationIfNeeds() { if (_calcSpecification == null) { _calcSpecification = createEmptyCalcSpecification(); } } protected HpCalcSpecification createEmptyCalcSpecification() { final SpecifyQuery emptySpecifyQuery = createEmptySpecifyQuery(); final HpCalcSpecification spec = newCalcSpecification(emptySpecifyQuery); spec.synchronizeSetupSelectByJourneyLogBook(); return spec; } protected SpecifyQuery createEmptySpecifyQuery() { return new SpecifyQuery() { public void specify(ConditionBean cb) { } }; } protected HpCalcSpecification newCalcSpecification(SpecifyQuery emptySpecifyQuery) { return new HpCalcSpecification(emptySpecifyQuery); } public boolean hasOrderByCalculation() { return _calcSpecification != null; } public HpCalcSpecification getOrderByCalculation() { return _calcSpecification; } public void xinitOrderByCalculation(ConditionBean baseCB, ConditionBean dreamCruiseCB) { if (!dreamCruiseCB.xisDreamCruiseShip()) { String msg = "The CB was not dream cruise: " + dreamCruiseCB.getClass(); throw new IllegalConditionBeanOperationException(msg); } _calcSpecification.setBaseCB(baseCB); _calcSpecification.specify(dreamCruiseCB); } // =================================================================================== // Connected Order // =============== public void toBeConnectionModeAsAnd() { _connectionMode = HpMobConnectionMode.AND; } public void toBeConnectionModeAsOr() { _connectionMode = HpMobConnectionMode.OR; } public void clearConnectionMode() { _connectionMode = null; } // =================================================================================== // CaseWhen Element // ================ protected HpMobCaseWhenElement createElement(ConditionKey conditionKey, Object orderValue) { return new HpMobCaseWhenElement(conditionKey, orderValue); } // =================================================================================== // Binding Process // =============== /** * Bind parameters for manual order.
* It is called from DBFlute runtime internally. * @param handler The handler for free parameters. (NotNull) */ public void bind(HpManualOrderThemeListHandler handler) { // called when set to query if (!hasManualOrder()) { return; } for (HpMobCaseWhenElement topElement : _caseWhenAcceptedList) { final HpMobCaseWhenElement boundTopElement = doBindCaseWhen(handler, topElement); final List connectedList = topElement.getConnectedElementList(); for (HpMobCaseWhenElement connectedElement : connectedList) { final HpMobCaseWhenElement boundConnectedElement = doBindCaseWhen(handler, connectedElement); boundTopElement.addConnectedElement(boundConnectedElement); } _caseWhenBoundList.add(boundTopElement); } doBindElseEnd(handler); } protected HpMobCaseWhenElement doBindCaseWhen(HpManualOrderThemeListHandler handler, HpMobCaseWhenElement element) { final ConditionKey conditionKey = element.getConditionKey(); final Object orderValue = resolveBoundValue(handler, element.getOrderValue(), false); final HpMobCaseWhenElement boundElement = createElement(conditionKey, orderValue); boundElement.setConnectionMode(element.getConnectionMode()); boundElement.setThenValue(resolveBoundValue(handler, element.getThenValue(), _suppressThenBinding)); return boundElement; } protected void doBindElseEnd(HpManualOrderThemeListHandler handler) { if (_elseAcceptedValue != null) { _elseBoundValue = resolveBoundValue(handler, _elseAcceptedValue, _suppressElseBinding); } } // ----------------------------------------------------- // Resolve Bound // ------------- protected Object resolveBoundValue(HpManualOrderThemeListHandler handler, Object plainValue, boolean suppressBinding) { if (plainValue == null) { return null; } if (plainValue instanceof SpecifiedColumn) { return resolveDreamCruiseExp(plainValue); } ClassificationCodeType codeType = null; if (plainValue instanceof Classification) { final Classification cls = (Classification) plainValue; plainValue = handleClassificationOrderValue(cls); codeType = cls.meta().codeType(); } final Object boundExp; if (suppressBinding) { if (plainValue instanceof String) { if (canBeLiteralClassificationCodeType(codeType)) { boundExp = plainValue; } else { String notice = "The binding of string value is unsupported on the DBMS."; throwUnsupportedTypeSpecifiedException(notice, plainValue); boundExp = null; // unreachable } } else if (plainValue instanceof Number) { boundExp = buildLiteralNumberExpression(plainValue); } else if (isAnyLocalDate(plainValue) || plainValue instanceof Date) { // #date_parade boundExp = buildLiteralDateExpression(plainValue); } else { String notice = "The binding of the type is unsupported on the DBMS."; throwUnsupportedTypeSpecifiedException(notice, plainValue); boundExp = null; // unreachable } } else { boundExp = handler.register(THEME_KEY, plainValue); } return boundExp; } protected Object resolveDreamCruiseExp(Object plainValue) { final SpecifiedColumn specifiedColumn = (SpecifiedColumn) plainValue; final String columnExp = specifiedColumn.toColumnRealName().toString(); if (specifiedColumn.hasSpecifyCalculation()) { specifiedColumn.xinitSpecifyCalculation(); final HpCalcSpecification calcSpecification = specifiedColumn.getSpecifyCalculation(); return calcSpecification.buildStatementToSpecifidName(columnExp); } return columnExp; } // ----------------------------------------------------- // Classification // -------------- protected Object handleClassificationOrderValue(Classification cls) { final Object orderValue; final String plainCode = cls.code(); final ClassificationCodeType codeType = cls.meta().codeType(); if (ClassificationCodeType.Number.equals(codeType)) { if ("true".equalsIgnoreCase(plainCode) || "false".equalsIgnoreCase(plainCode)) { // true or false of Number, e.g. MySQL's Boolean orderValue = toClassificationBooleanValue(plainCode); } else { orderValue = toClassificationIntegerValue(plainCode); } } else if (ClassificationCodeType.Boolean.equals(codeType)) { orderValue = toClassificationBooleanValue(plainCode); } else { orderValue = plainCode; } return orderValue; } protected Integer toClassificationIntegerValue(String plainCode) { return (Integer) DfTypeUtil.toNumber(plainCode, Integer.class); } protected Boolean toClassificationBooleanValue(String plainCode) { return DfTypeUtil.toBoolean(plainCode); } protected boolean canBeLiteralClassificationCodeType(ClassificationCodeType codeType) { return codeType != null && codeType.equals(ClassificationCodeType.Number) && codeType.equals(ClassificationCodeType.Boolean); } // ----------------------------------------------------- // Number Handling // --------------- protected String buildLiteralNumberExpression(Object plainValue) { return plainValue.toString(); } // ----------------------------------------------------- // Date Handling // ------------- protected boolean isAnyLocalDate(Object plainValue) { return DfTypeUtil.isAnyLocalDate(plainValue); } protected String buildLiteralDateExpression(Object plainValue) { if (plainValue instanceof LocalDate) { // local date cannot use time-part so check it final String pattern = DisplaySqlBuilder.DEFAULT_DATE_FORMAT; return doBuildLiteralDateExpression(DfTypeUtil.toStringDate((LocalDate) plainValue, pattern)); } else if (plainValue instanceof LocalDateTime) { final String pattern = DisplaySqlBuilder.DEFAULT_TIMESTAMP_FORMAT; return doBuildLiteralDateExpression(DfTypeUtil.toStringDate((LocalDateTime) plainValue, pattern)); } else if (plainValue instanceof LocalTime) { final String pattern = DisplaySqlBuilder.DEFAULT_TIME_FORMAT; return doBuildLiteralDateExpression(DfTypeUtil.toStringDate((LocalTime) plainValue, pattern)); } else { // instance of util.Date, as time-stamp fixedly (since 1.0.x) final String pattern = DisplaySqlBuilder.DEFAULT_TIMESTAMP_FORMAT; return doBuildLiteralDateExpression(DfTypeUtil.toString(plainValue, pattern)); } } protected String doBuildLiteralDateExpression(String formatted) { return "'" + formatted + "'"; } // ----------------------------------------------------- // Exception Handling // ------------------ protected void throwUnsupportedTypeSpecifiedException(String notice, Object plainValue) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice(notice); br.addItem("Advice"); br.addElement("The binding for the part, 'when' or 'then' or 'else',"); br.addElement("is unsupported with the value type."); br.addItem("Specified Value"); br.addElement(plainValue.getClass()); br.addElement(plainValue); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } // ----------------------------------------------------- // Then/Else Binding // ----------------- public ManualOrderOption suppressThenBinding() { _suppressThenBinding = true; return this; } public ManualOrderOption suppressElseBinding() { _suppressElseBinding = true; return this; } // =================================================================================== // Validation // ========== /** * Validate case-when constraints.
* It is called from DBFlute runtime internally. */ public void validate() { // called when set to query doValidateCaseWhenConstraint(); } protected void doValidateCaseWhenConstraint() { if (_caseWhenAcceptedList.isEmpty()) { return; } final HpMobCaseWhenElement first = _caseWhenAcceptedList.get(0); final boolean firstThenExists = first.getThenValue() != null; for (HpMobCaseWhenElement current : _caseWhenAcceptedList) { final boolean currentThenExists = current.getThenValue() != null; if (firstThenExists && !currentThenExists) { throwManualOrderRequiredThenNotFoundException(current); } else if (!firstThenExists && currentThenExists) { throwManualOrderUnnecessaryThenFoundException(current); } } final boolean elseExists = _elseAcceptedValue != null; if (firstThenExists && !elseExists) { // e.g. SwitchOrder throwManualOrderRequiredElseNotFoundException(); } else if (!firstThenExists && elseExists) { // e.g. PriorityOrder String msg = "Found unnecessary 'else', it doesn't need it if PriorityOrder: " + toString(); throw new IllegalConditionBeanOperationException(msg); } } protected void throwManualOrderRequiredThenNotFoundException(HpMobCaseWhenElement current) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Not found 'then', all elements need it (if SwitchOrder)."); br.addItem("Advice"); br.addElement("You should set 'then' value to all case-when elements"); br.addElement("if you want to use SwitchOrder."); br.addElement("(settings for 'then' value means SwitchOrder)"); br.addElement("For example:"); br.addElement(" (x):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7).then(...);"); br.addElement(" mob.when_LessThan(3); // *NG"); br.addElement(" (o):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7).then(...);"); br.addElement(" mob.when_LessThan(3).then(...); // OK"); br.addItem("Target Element"); br.addElement(current); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } protected void throwManualOrderUnnecessaryThenFoundException(HpMobCaseWhenElement current) { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Found unnecessary 'then', all elements doesn't need it (if PriorityOrder)."); br.addItem("Advice"); br.addElement("You should NOT set 'then' value to all case-when elements"); br.addElement("if you want to use PriorityOrder."); br.addElement("(No 'then' value means PriorityOrder)"); br.addElement("For example:"); br.addElement(" (x):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7);"); br.addElement(" mob.when_LessThan(3).then(...); // *NG"); br.addElement(" (o):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7);"); br.addElement(" mob.when_LessThan(3); // OK"); br.addItem("Target Element"); br.addElement(current); final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } protected void throwManualOrderRequiredElseNotFoundException() { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Not found 'else', it needs it (if SwitchOrder)."); br.addItem("Advice"); br.addElement("You should set 'else' value if you want to use SwitchOrder."); br.addElement("(settings for 'then' value means SwitchOrder)"); br.addElement("For example:"); br.addElement(" (x):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7).then(...);"); br.addElement(" mob.when_LessThan(3).then(...);"); br.addElement(" cb.query().addOrderBy_...().withManualOrder(mob); // *NG"); br.addElement(" (o):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7).then(...);"); br.addElement(" mob.when_LessThan(3).then(...);"); br.addElement(" mob.elseEnd(3); // OK"); br.addElement(" cb.query().addOrderBy_...().withManualOrder(mob);"); br.addItem("CaseWhen Element"); for (HpMobCaseWhenElement element : _caseWhenAcceptedList) { br.addElement(element); } final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } protected void throwManualOrderUnnecessaryElseNotFoundException() { final ExceptionMessageBuilder br = new ExceptionMessageBuilder(); br.addNotice("Found unnecessary 'else', it doesn't need it (if PriorityOrder)."); br.addItem("Advice"); br.addElement("You should NOT set 'else' value if you want to use PriorityOrder."); br.addElement("(No 'then' value means PriorityOrder)"); br.addElement("For example:"); br.addElement(" (x):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7);"); br.addElement(" mob.when_LessThan(3);"); br.addElement(" mob.elseEnd(3); // *NG"); br.addElement(" (o):"); br.addElement(" ManualOrderOption mob = new ManualOrderOption();"); br.addElement(" mob.when_GreaterThan(7);"); br.addElement(" mob.when_LessThan(3);"); br.addElement(" cb.query().addOrderBy_...().withManualOrder(mob); // OK"); br.addItem("CaseWhen Element"); for (HpMobCaseWhenElement element : _caseWhenAcceptedList) { br.addElement(element); } final String msg = br.buildExceptionMessage(); throw new IllegalConditionBeanOperationException(msg); } // =================================================================================== // Determination // ============= public boolean hasManualOrder() { return !_caseWhenAcceptedList.isEmpty() || _calcSpecification != null; } // =================================================================================== // Assert Helper // ============= protected void assertObjectNotNull(String variableName, Object value) { if (variableName == null) { String msg = "The value should not be null: variableName=null value=" + value; throw new IllegalArgumentException(msg); } if (value == null) { String msg = "The value should not be null: variableName=" + variableName; throw new IllegalArgumentException(msg); } } protected void assertCalculationColumnNumber(SpecifiedColumn specifiedColumn) { final ColumnInfo columnInfo = specifiedColumn.getColumnInfo(); if (columnInfo == null) { // basically not null but just in case return; } if (!columnInfo.isObjectNativeTypeNumber()) { String msg = "The type of the calculation column should be Number: " + specifiedColumn; throw new IllegalArgumentException(msg); } } protected void assertSpecifiedDreamCruiseTicket(SpecifiedColumn column) { if (!column.isDreamCruiseTicket()) { final String msg = "The specified column was not dream cruise ticket: " + column; throw new IllegalConditionBeanOperationException(msg); } } // =================================================================================== // Time Management // =============== protected Date toDate(Object obj) { return DfTypeUtil.toDate(obj, getFromToConversionTimeZone()); } protected TimeZone getFromToConversionTimeZone() { return getDBFluteSystemFinalTimeZone(); } protected TimeZone getDBFluteSystemFinalTimeZone() { return DBFluteSystem.getFinalTimeZone(); } // =================================================================================== // Basic Override // ============== // *instance match so does not override equals() @Override public String toString() { final String title = DfTypeUtil.toClassTitle(this); return title + ":{case-when=" + _caseWhenAcceptedList.size() + ", calc=" + _calcSpecification + "}"; } // =================================================================================== // Accessor // ======== public List getCaseWhenAcceptedList() { return _caseWhenAcceptedList; } public List getCaseWhenBoundList() { return _caseWhenBoundList; } /** * Get the 'else' value, which is bound.
* It returns null if you set only 'else' value but not binding. * @return The value for 'else'. (NullAllowed) */ public Object getElseValue() { return _elseBoundValue; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy